From 2625ab3ccdafd8d474018516e6aa36ce48989db3 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Thu, 5 Nov 2015 16:32:02 +0200 Subject: [PATCH 001/142] rtpengine: hash table to keep the selected nodes Shared memory hash table with global hashtable lock. Add state maintaining the selected rtp node, for a given callid. Hashtable entry expiration time configurable using hash_entry_tout modparam. The actual deletion happens on the fly while insert/remove/lookup are called. Updated doku. --- modules/rtpengine/doc/rtpengine_admin.xml | 26 ++ modules/rtpengine/rtpengine.c | 189 ++++++++++--- modules/rtpengine/rtpengine_hash.c | 314 ++++++++++++++++++++++ modules/rtpengine/rtpengine_hash.h | 30 +++ 4 files changed, 523 insertions(+), 36 deletions(-) create mode 100644 modules/rtpengine/rtpengine_hash.c create mode 100644 modules/rtpengine/rtpengine_hash.h diff --git a/modules/rtpengine/doc/rtpengine_admin.xml b/modules/rtpengine/doc/rtpengine_admin.xml index b447387dac2..bcb1c030ea4 100644 --- a/modules/rtpengine/doc/rtpengine_admin.xml +++ b/modules/rtpengine/doc/rtpengine_admin.xml @@ -356,6 +356,32 @@ modparam("rtpproxy", "rtp_inst_pvar", "$avp(RTP_INSTANCE)") +
+ <varname>hash_entry_tout</varname> (string) + + Number of seconds after an rtpengine hash table entry is marked for deletion. + By default, this parameter is set to 120 (seconds). + + + To maintain information about a selected rtp machine node, for a given call, entries are added in a hashtable of (callid, node) pairs. + When "offer" comes, insert new entry in the hastable. + When subsequent commands come, lookup callid and return chosen node. + When "delete" comes, remove old entry from hashtable. + + + NOTE: In the current implementation, the actual deletion happens on the fly, + while insert/remove/lookup the hastable, only for the entries in the insert/remove/lookup path. + + + Set <varname>hash_entry_tout</varname> parameter + +... +modparam("rtpproxy", "hash_entry_tout", "300") +... + + +
+
diff --git a/modules/rtpengine/rtpengine.c b/modules/rtpengine/rtpengine.c index 86211cc2211..e1ec46c8dca 100644 --- a/modules/rtpengine/rtpengine.c +++ b/modules/rtpengine/rtpengine.c @@ -78,6 +78,7 @@ #include "../../modules/tm/tm_load.h" #include "rtpengine.h" #include "rtpengine_funcs.h" +#include "rtpengine_hash.h" #include "bencode.h" MODULE_VERSION @@ -187,7 +188,9 @@ static int rtpengine_offer_answer(struct sip_msg *msg, const char *flags, int op static int fixup_set_id(void ** param, int param_no); static int set_rtpengine_set_f(struct sip_msg * msg, char * str1, char * str2); static struct rtpp_set * select_rtpp_set(int id_set); -static struct rtpp_node *select_rtpp_node(str, int); +static struct rtpp_node *select_rtpp_node_new(str, int, int); +static struct rtpp_node *select_rtpp_node_old(str, int, int); +static struct rtpp_node *select_rtpp_node(str, int, int); static char *send_rtpp_command(struct rtpp_node *, bencode_item_t *, int *); static int get_extra_id(struct sip_msg* msg, str *id_str); @@ -228,6 +231,7 @@ static pid_t mypid; static unsigned int myseqn = 0; static str extra_id_pv_param = {NULL, 0}; static char *setid_avp_param = NULL; +static int hash_entry_tout = 120; static char ** rtpp_strings=0; static int rtpp_sets=0; /*used in rtpengine_set_store()*/ @@ -336,6 +340,7 @@ static param_export_t params[] = { {"rtp_inst_pvar", PARAM_STR, &rtp_inst_pv_param }, {"write_sdp_pv", PARAM_STR, &write_sdp_pvar_str }, {"read_sdp_pv", PARAM_STR, &read_sdp_pvar_str }, + {"hash_entry_tout", INT_PARAM, &hash_entry_tout }, {0, 0, 0} }; @@ -1440,6 +1445,14 @@ mod_init(void) return -1; } + /* init the hastable which keeps the call-id <-> selected_node relation */ + if (!rtpengine_hash_table_init()) { + LM_ERR("rtpengine_hash_table_init() failed!\n"); + return -1; + } else { + LM_DBG("rtpengine_hash_table_init() success!\n"); + } + return 0; } @@ -1579,6 +1592,13 @@ static void mod_destroy(void) } shm_free(rtpp_set_list); + + /* destroy the hastable which keeps the call-id <-> selected_node relation */ + if (!rtpengine_hash_table_destroy()) { + LM_ERR("rtpengine_hash_table_destroy() failed!\n"); + } else { + LM_DBG("rtpengine_hash_table_destroy() success!\n"); + } } @@ -1923,16 +1943,17 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_ LM_ERR("queried nodes limit reached\n"); goto error; } - node = select_rtpp_node(callid, 1); + node = select_rtpp_node(callid, 1, op); if (!node) { LM_ERR("no available proxies\n"); goto error; } + cp = send_rtpp_command(node, ng_flags.dict, &ret); - if (cp == NULL) { - node->rn_disabled = 1; - node->rn_recheck_ticks = get_ticks() + rtpengine_disable_tout; - } + if (cp == NULL) { + node->rn_disabled = 1; + node->rn_recheck_ticks = get_ticks() + rtpengine_disable_tout; + } } while (cp == NULL); LM_DBG("proxy reply: %.*s\n", ret, cp); @@ -1944,12 +1965,13 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_ LM_ERR("failed to decode bencoded reply from proxy: %.*s\n", ret, cp); goto error; } + if (!bencode_dictionary_get_strcmp(resp, "result", "error")) { if (!bencode_dictionary_get_str(resp, "error-reason", &error)) { LM_ERR("proxy return error but didn't give an error reason: %.*s\n", ret, cp); } else { - if ((RTPENGINE_SESS_LIMIT_MSG_LEN == error.len) && + if ((RTPENGINE_SESS_LIMIT_MSG_LEN == error.len) && (strncmp(error.s, RTPENGINE_SESS_LIMIT_MSG, RTPENGINE_SESS_LIMIT_MSG_LEN) == 0)) { LM_WARN("proxy %.*s: %.*s", node->rn_url.len, node->rn_url.s , error.len, error.s); @@ -1957,12 +1979,23 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_ } LM_ERR("proxy replied with error: %.*s\n", error.len, error.s); } - goto error; + goto error; } if (body_out) *body_out = body; + if (op == OP_DELETE) { + /* Delete the key<->value from the hashtable */ + if (!rtpengine_hash_table_remove(&callid)) { + LM_ERR("rtpengine hash table failed to remove entry for callen=%d callid=%.*s\n", + callid.len, callid.len, callid.s); + } else { + LM_DBG("rtpengine hash table remove entry for callen=%d callid=%.*s\n", + callid.len, callid.len, callid.s); + } + } + return resp; error: @@ -2191,81 +2224,165 @@ static struct rtpp_set * select_rtpp_set(int id_set ){ return rtpp_list; } + /* - * Main balancing routine. This does not try to keep the same proxy for - * the call if some proxies were disabled or enabled; proxy death considered - * too rare. Otherwise we should implement "mature" HA clustering, which is - * too expensive here. + * run the selection algorithm and return the new selected node */ static struct rtpp_node * -select_rtpp_node(str callid, int do_test) +select_rtpp_node_new(str callid, int do_test, int op) { - unsigned sum, sumcut, weight_sum; struct rtpp_node* node; - int was_forced; - - if(!active_rtpp_set){ - LM_ERR("script error -no valid set selected\n"); - return NULL; - } - /* Most popular case: 1 proxy, nothing to calculate */ - if (active_rtpp_set->rtpp_node_count == 1) { - node = active_rtpp_set->rn_first; - if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()) - node->rn_disabled = rtpp_test(node, 1, 0); - return node->rn_disabled ? NULL : node; - } + unsigned i, sum, sumcut, weight_sum; + int was_forced = 0; /* XXX Use quick-and-dirty hashing algo */ - for(sum = 0; callid.len > 0; callid.len--) - sum += callid.s[callid.len - 1]; + for(i = 0; i < callid.len; i++) + sum += callid.s[i]; sum &= 0xff; - was_forced = 0; retry: weight_sum = 0; - for (node=active_rtpp_set->rn_first; node!=NULL; node=node->rn_next) { + for (node=active_rtpp_set->rn_first; node!=NULL; node=node->rn_next) { + /* Try to enable if it's time to try. */ if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()){ - /* Try to enable if it's time to try. */ node->rn_disabled = rtpp_test(node, 1, 0); } - if (!node->rn_disabled) + + /* Select only between enabled machines */ + if (!node->rn_disabled) { weight_sum += node->rn_weight; + } } + + /* No proxies? Force all to be redetected, if not yet */ if (weight_sum == 0) { - /* No proxies? Force all to be redetected, if not yet */ - if (was_forced) + if (was_forced) { return NULL; + } + was_forced = 1; + for(node=active_rtpp_set->rn_first; node!=NULL; node=node->rn_next) { node->rn_disabled = rtpp_test(node, 1, 1); } + goto retry; } + + /* sumcut here lays from 0 to weight_sum-1 */ sumcut = sum % weight_sum; + /* - * sumcut here lays from 0 to weight_sum-1. * Scan proxy list and decrease until appropriate proxy is found. */ for (node=active_rtpp_set->rn_first; node!=NULL; node=node->rn_next) { + /* Select only between enabled machines */ if (node->rn_disabled) continue; + + /* Found enabled machine */ if (sumcut < node->rn_weight) goto found; + + /* Update sumcut if enabled machine */ sumcut -= node->rn_weight; } + /* No node list */ return NULL; + found: if (do_test) { node->rn_disabled = rtpp_test(node, node->rn_disabled, 0); if (node->rn_disabled) goto retry; } + + /* build hash table entry */ + struct rtpengine_hash_entry *entry = shm_malloc(sizeof(struct rtpp_node)); + if (shm_str_dup(&entry->callid, &callid) < 0) { + LM_ERR("rtpengine hash table fail to duplicate calllen=%d callid=%.*s", + callid.len, callid.len, callid.s); + } + entry->node = node; + entry->next = NULL; + entry->tout = get_ticks() + hash_entry_tout; + + /* Insert the key<->entry from the hashtable */ + if (!rtpengine_hash_table_insert(&callid, entry)) { + LM_ERR("rtpengine hash table fail to insert node=%.*s for calllen=%d callid=%.*s", + node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); + } else { + LM_DBG("rtpengine hash table insert node=%.*s for calllen=%d callid=%.*s\n", + node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); + } + + /* Return selected node */ return node; } +/* + * lookup the hastable (key=callid value=node) and get the old node + */ +static struct rtpp_node * +select_rtpp_node_old(str callid, int do_test, int op) +{ + struct rtpp_node *node = NULL; + struct rtpengine_hash_entry *entry = NULL; + + entry = rtpengine_hash_table_lookup(&callid); + if (!entry) { + LM_ERR("rtpengine hash table lookup failed to find entry for calllen=%d callid=%.*s\n", + callid.len, callid.len, callid.s); + } else { + LM_DBG("rtpengine hash table lookup find entry for calllen=%d callid=%.*s\n", + callid.len, callid.len, callid.s); + node = entry->node; + } + + if (!node) { + LM_ERR("rtpengine hash table lookup failed to find node for calllen=%d callid=%.*s\n", + callid.len, callid.len, callid.s); + return NULL; + } else { + LM_DBG("rtpengine hash table lookup find node=%.*s for calllen=%d callid=%.*s\n", + node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); + } + + // if node broke, don't send any message + if (!node->rn_disabled) { + return node; + } else { + LM_DBG("rtpengine hash table lookup find node=%.*s for calllen=%d callid=%.*s, which is disabled!\n", + node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); + } + + return NULL; +} + +/* + * Main balancing routine. This DO try to keep the same proxy for + * the call if some proxies were disabled or enabled (e.g. kamctl command) + */ +static struct rtpp_node * +select_rtpp_node(str callid, int do_test, int op) +{ + if(!active_rtpp_set) { + LM_ERR("script error - no valid set selected\n"); + return NULL; + } + + // calculate and choose a node + if (op == OP_OFFER) { + // run the selection algorithm + return select_rtpp_node_new(callid, do_test, op); + } else { + // lookup the hastable (key=callid value=node) and get the old node + return select_rtpp_node_old(callid, do_test, op); + } +} + static int get_extra_id(struct sip_msg* msg, str *id_str) { if(msg==NULL || extra_id_pv==NULL || id_str==NULL) { diff --git a/modules/rtpengine/rtpengine_hash.c b/modules/rtpengine/rtpengine_hash.c new file mode 100644 index 00000000000..f23b45db48c --- /dev/null +++ b/modules/rtpengine/rtpengine_hash.c @@ -0,0 +1,314 @@ +#include "rtpengine_hash.h" + +#include "../../str.h" +#include "../../dprint.h" +#include "../../mem/shm_mem.h" +#include "../../locking.h" +#include "../../timer.h" + +static gen_lock_t *rtpengine_hash_lock; +static struct rtpengine_hash_table *rtpengine_hash_table; + +/* from sipwise rtpengine */ +static int str_cmp_str(const str *a, const str *b) { + if (a->len < b->len) + return -1; + if (a->len > b->len) + return 1; + if (a->len == 0 && b->len == 0) + return 0; + return memcmp(a->s, b->s, a->len); +} + +/* from sipwise rtpengine */ +static int str_equal(void *a, void *b) { + return (str_cmp_str((str *) a, (str *) b) == 0); +} + +/* from sipwise rtpengine */ +static unsigned int str_hash(void *ss) { + const str *s = (str*) ss; + unsigned int ret = 5381; + str it = *s; + + while (it.len > 0) { + ret = (ret << 5) + ret + *it.s; + it.s++; + it.len--; + } + + return ret % RTPENGINE_HASH_TABLE_SIZE; +} + +/* rtpengine glib hash API */ +int rtpengine_hash_table_init() { + int i; + + // init hashtable + rtpengine_hash_table = shm_malloc(sizeof(struct rtpengine_hash_table)); + if (!rtpengine_hash_table) { + LM_ERR("no shm left to create rtpengine_hash_table\n"); + return 0; + } + + // init hashtable entry_list heads (never filled) + for (i = 0; i < RTPENGINE_HASH_TABLE_SIZE; i++) { + rtpengine_hash_table->entry_list[i] = shm_malloc(sizeof(struct rtpengine_hash_entry)); + if (!rtpengine_hash_table->entry_list[i]) { + LM_ERR("no shm left to create rtpengine_hash_table->entry_list[%d]\n", i); + return 0; + } + + /* never expire the head of the hashtable index lists */ + rtpengine_hash_table->entry_list[i]->tout = -1; + rtpengine_hash_table->entry_list[i]->next = NULL; + } + + // init lock + rtpengine_hash_lock = lock_alloc(); + if (!rtpengine_hash_lock) { + LM_ERR("no shm left to init rtpengine_hash_table lock"); + return 0; + } + + return 1; +} + +int rtpengine_hash_table_destroy() { + int i; + struct rtpengine_hash_entry *entry, *last_entry; + + // check rtpengine hashtable + if (!rtpengine_hash_table) { + LM_ERR("NULL rtpengine_hash_table"); + return 0; + } + + // destroy hashtable entry_list content + lock_get(rtpengine_hash_lock); + for (i = 0; i < RTPENGINE_HASH_TABLE_SIZE; i++) { + entry = rtpengine_hash_table->entry_list[i]; + while (entry) { + last_entry = entry; + entry = entry->next; + shm_free(last_entry->callid.s); + shm_free(last_entry); + } + } + + // destroy hashtable + shm_free(rtpengine_hash_table); + rtpengine_hash_table = NULL; + lock_release(rtpengine_hash_lock); + + // destroy lock + if (!rtpengine_hash_lock) { + LM_ERR("NULL rtpengine_hash_lock"); + } else { + lock_dealloc(rtpengine_hash_lock); + rtpengine_hash_lock = NULL; + } + + return 1; +} + +int rtpengine_hash_table_insert(void *key, void *value) { + struct rtpengine_hash_entry *entry, *last_entry; + struct rtpengine_hash_entry *new_entry = (struct rtpengine_hash_entry *) value; + unsigned int hash_index; + + // check rtpengine hashtable + if (!rtpengine_hash_table) { + LM_ERR("NULL rtpengine_hash_table"); + return 0; + } + + // get entry list + hash_index = str_hash(key); + entry = rtpengine_hash_table->entry_list[hash_index]; + last_entry = entry; + + // lock + lock_get(rtpengine_hash_lock); + while (entry) { + // if key found, don't add new entry + if (str_equal(&entry->callid, &new_entry->callid)) { + // unlock + lock_release(rtpengine_hash_lock); + LM_ERR("Call id %.*s already in hashtable, ignore new value", entry->callid.len, entry->callid.s); + return 0; + } + + // if expired entry discovered, delete it + if (entry->tout < get_ticks()) { + // set pointers; exclude entry + last_entry->next = entry->next; + + // free current entry; entry points to unknown + shm_free(entry->callid.s); + shm_free(entry); + + // set pointers + entry = last_entry; + } + + // next entry in the list + last_entry = entry; + entry = entry->next; + } + + last_entry->next = new_entry; + + // unlock + lock_release(rtpengine_hash_lock); + + return 1; +} + +int rtpengine_hash_table_remove(void *key) { + struct rtpengine_hash_entry *entry, *last_entry; + unsigned int hash_index; + + // check rtpengine hashtable + if (!rtpengine_hash_table) { + LM_ERR("NULL rtpengine_hash_table"); + return 0; + } + + // get first entry from entry list; jump over unused list head + hash_index = str_hash(key); + entry = rtpengine_hash_table->entry_list[hash_index]; + last_entry = entry; + + // lock + lock_get(rtpengine_hash_lock); + while (entry) { + // if key found, delete entry + if (str_equal(&entry->callid, (str *)key)) { + // free entry + last_entry->next = entry->next; + shm_free(entry->callid.s); + shm_free(entry); + + // unlock + lock_release(rtpengine_hash_lock); + + return 1; + } + + // if expired entry discovered, delete it + if (entry->tout < get_ticks()) { + // set pointers; exclude entry + last_entry->next = entry->next; + + // free current entry; entry points to unknown + shm_free(entry->callid.s); + shm_free(entry); + + // set pointers + entry = last_entry; + } + + last_entry = entry; + entry = entry->next; + } + + // unlock + lock_release(rtpengine_hash_lock); + + return 0; +} + +void* rtpengine_hash_table_lookup(void *key) { + struct rtpengine_hash_entry *entry, *last_entry; + unsigned int hash_index; + + // check rtpengine hashtable + if (!rtpengine_hash_table) { + LM_ERR("NULL rtpengine_hash_table"); + return 0; + } + + // get first entry from entry list; jump over unused list head + hash_index = str_hash(key); + entry = rtpengine_hash_table->entry_list[hash_index]; + last_entry = entry; + + // lock + lock_get(rtpengine_hash_lock); + while (entry) { + // if key found, return entry + if (str_equal(&entry->callid, (str *)key)) { + // unlock + lock_release(rtpengine_hash_lock); + + return entry; + } + + // if expired entry discovered, delete it + if (entry->tout < get_ticks()) { + // set pointers; exclude entry + last_entry->next = entry->next; + + // free current entry; entry points to unknown + shm_free(entry->callid.s); + shm_free(entry); + + // set pointers + entry = last_entry; + } + + last_entry = entry; + entry = entry->next; + } + + // unlock + lock_release(rtpengine_hash_lock); + + return NULL; +} + +// print hash table entries while deleting expired entries +void rtpengine_hash_table_print() { + int i; + struct rtpengine_hash_entry *entry, *last_entry; + + // check rtpengine hashtable + if (!rtpengine_hash_table) { + LM_ERR("NULL rtpengine_hash_table"); + return ; + } + + // lock + lock_get(rtpengine_hash_lock); + + // print hashtable + for (i = 0; i < RTPENGINE_HASH_TABLE_SIZE; i++) { + entry = rtpengine_hash_table->entry_list[i]; + last_entry = entry; + + while (entry) { + // if expired entry discovered, delete it + if (entry->tout < get_ticks()) { + // set pointers; exclude entry + last_entry->next = entry->next; + + // free current entry; entry points to unknown + shm_free(entry->callid.s); + shm_free(entry); + + // set pointers + entry = last_entry; + } else { + LM_DBG("hash_index=%d callid=%.*s tout=%u\n", + i, entry->callid.len, entry->callid.s, entry->tout - get_ticks()); + } + + last_entry = entry; + entry = entry->next; + } + } + + // unlock + lock_release(rtpengine_hash_lock); +} diff --git a/modules/rtpengine/rtpengine_hash.h b/modules/rtpengine/rtpengine_hash.h new file mode 100644 index 00000000000..71a73b45b1e --- /dev/null +++ b/modules/rtpengine/rtpengine_hash.h @@ -0,0 +1,30 @@ +#ifndef _RTPENGINE_HASH_H +#define _RTPENGINE_HASH_H + +#include "../../str.h" + +#define RTPENGINE_HASH_TABLE_SIZE 512 + +/* table entry */ +struct rtpengine_hash_entry { + unsigned int tout; // call timeout + str callid; // call callid + struct rtpp_node *node; // call selected node + + struct rtpengine_hash_entry *next; // next +}; + +/* table */ +struct rtpengine_hash_table { + struct rtpengine_hash_entry *entry_list[RTPENGINE_HASH_TABLE_SIZE]; +}; + + +int rtpengine_hash_table_init(); +int rtpengine_hash_table_destroy(); +int rtpengine_hash_table_insert(void *key, void *value); +int rtpengine_hash_table_remove(void *key); +void* rtpengine_hash_table_lookup(void *key); +void rtpengine_hash_table_print() ; + +#endif From 02d8a62260fa1d1e98db4a9b5f4cdac8cab1ea4b Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Fri, 6 Nov 2015 17:12:23 +0200 Subject: [PATCH 002/142] rtpengine: Update doku for node enable/disable This is my understanding of the current shared memory node list implementation. Correct me if I'm wrong. --- modules/rtpengine/doc/rtpengine_admin.xml | 32 +++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/modules/rtpengine/doc/rtpengine_admin.xml b/modules/rtpengine/doc/rtpengine_admin.xml index bcb1c030ea4..2454db2aa05 100644 --- a/modules/rtpengine/doc/rtpengine_admin.xml +++ b/modules/rtpengine/doc/rtpengine_admin.xml @@ -73,6 +73,38 @@ If the set was selected using setid_avp, the avp needs to be set only once before rtpengine_offer() or rtpengine_manage() call. + + From the current implementation point of view, the sets of rtpproxy nodes + are shared memory(shm), so all processes can see a common list of nodes. + There is no locking when setting the nodes enabled/disabled (to keep the + memory access as fast as possible). Thus, problems related to node state + might appear for concurent processes that might set the nodes + enabled/disabled(e.g. by fifo command). This robustness problems are overcomed as follows. + + + + If the current process sees the selected node as disabled, the node is + force tested before the current process actually + takes the disabled decision. If the test succeeds, the process will set + the node as enabled (but other concurrent process might still see it as disabled). +. + + + + If the current process sees the selected node as enabled, it does no additional checks + and sends the command which will fail in case the machine is actually broken. + The process will set the node as disabled (but other concurrent process might still see it as enabled). + + + + The 'kamctl fifo' commands (including rtpengin ones) are executed by an exclusive + process which operate on the same shared memory node list. + + + + All the nodes are pinged in the beginning by all the processes, + even if the node list is shared memory. +
From 7375d0b8f136c09d5f4597338aae2d50214a3293 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Mon, 9 Nov 2015 12:54:47 +0200 Subject: [PATCH 003/142] rtpengine: Add hash_table_size modparam Allow configurable table size. Updated doku. --- modules/rtpengine/doc/rtpengine_admin.xml | 27 +++++++++++++++++--- modules/rtpengine/rtpengine.c | 14 +++++----- modules/rtpengine/rtpengine_hash.c | 31 +++++++++++++++++------ modules/rtpengine/rtpengine_hash.h | 7 +++-- 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/modules/rtpengine/doc/rtpengine_admin.xml b/modules/rtpengine/doc/rtpengine_admin.xml index 2454db2aa05..0c8a6477633 100644 --- a/modules/rtpengine/doc/rtpengine_admin.xml +++ b/modules/rtpengine/doc/rtpengine_admin.xml @@ -388,8 +388,26 @@ modparam("rtpproxy", "rtp_inst_pvar", "$avp(RTP_INSTANCE)")
-
- <varname>hash_entry_tout</varname> (string) +
+ <varname>hash_table_size</varname> (integer) + + Size of the hash table. Default value is 256. + + + NOTE: If configured size is less than 1, the size will be defaulted to 1. + + + Set <varname>hash_table_size</varname> parameter + +... +modparam("rtpproxy", "hash_table_size", "123") +... + + +
+ +
+ <varname>hash_table_tout</varname> (integer) Number of seconds after an rtpengine hash table entry is marked for deletion. By default, this parameter is set to 120 (seconds). @@ -405,15 +423,16 @@ modparam("rtpproxy", "rtp_inst_pvar", "$avp(RTP_INSTANCE)") while insert/remove/lookup the hastable, only for the entries in the insert/remove/lookup path. - Set <varname>hash_entry_tout</varname> parameter + Set <varname>hash_table_tout</varname> parameter ... -modparam("rtpproxy", "hash_entry_tout", "300") +modparam("rtpproxy", "hash_table_tout", "300") ...
+
diff --git a/modules/rtpengine/rtpengine.c b/modules/rtpengine/rtpengine.c index e1ec46c8dca..e48f31811e1 100644 --- a/modules/rtpengine/rtpengine.c +++ b/modules/rtpengine/rtpengine.c @@ -231,7 +231,8 @@ static pid_t mypid; static unsigned int myseqn = 0; static str extra_id_pv_param = {NULL, 0}; static char *setid_avp_param = NULL; -static int hash_entry_tout = 120; +static int hash_table_tout = 120; +static int hash_table_size = 256; static char ** rtpp_strings=0; static int rtpp_sets=0; /*used in rtpengine_set_store()*/ @@ -340,7 +341,8 @@ static param_export_t params[] = { {"rtp_inst_pvar", PARAM_STR, &rtp_inst_pv_param }, {"write_sdp_pv", PARAM_STR, &write_sdp_pvar_str }, {"read_sdp_pv", PARAM_STR, &read_sdp_pvar_str }, - {"hash_entry_tout", INT_PARAM, &hash_entry_tout }, + {"hash_table_tout", INT_PARAM, &hash_table_tout }, + {"hash_table_size", INT_PARAM, &hash_table_size }, {0, 0, 0} }; @@ -1446,11 +1448,11 @@ mod_init(void) } /* init the hastable which keeps the call-id <-> selected_node relation */ - if (!rtpengine_hash_table_init()) { - LM_ERR("rtpengine_hash_table_init() failed!\n"); + if (!rtpengine_hash_table_init(hash_table_size)) { + LM_ERR("rtpengine_hash_table_init(%d) failed!\n", hash_table_size); return -1; } else { - LM_DBG("rtpengine_hash_table_init() success!\n"); + LM_DBG("rtpengine_hash_table_init(%d) success!\n", hash_table_size); } return 0; @@ -2307,7 +2309,7 @@ select_rtpp_node_new(str callid, int do_test, int op) } entry->node = node; entry->next = NULL; - entry->tout = get_ticks() + hash_entry_tout; + entry->tout = get_ticks() + hash_table_tout; /* Insert the key<->entry from the hashtable */ if (!rtpengine_hash_table_insert(&callid, entry)) { diff --git a/modules/rtpengine/rtpengine_hash.c b/modules/rtpengine/rtpengine_hash.c index f23b45db48c..3cca5749f6e 100644 --- a/modules/rtpengine/rtpengine_hash.c +++ b/modules/rtpengine/rtpengine_hash.c @@ -8,6 +8,7 @@ static gen_lock_t *rtpengine_hash_lock; static struct rtpengine_hash_table *rtpengine_hash_table; +static int hash_table_size; /* from sipwise rtpengine */ static int str_cmp_str(const str *a, const str *b) { @@ -37,13 +38,21 @@ static unsigned int str_hash(void *ss) { it.len--; } - return ret % RTPENGINE_HASH_TABLE_SIZE; + return ret % hash_table_size; } /* rtpengine glib hash API */ -int rtpengine_hash_table_init() { +int rtpengine_hash_table_init(int size) { int i; + // init hash table size + if (size < 1) { + hash_table_size = 1; + } else { + hash_table_size = size; + } + LM_DBG("rtpengine_hash_table size = %d\n", hash_table_size); + // init hashtable rtpengine_hash_table = shm_malloc(sizeof(struct rtpengine_hash_table)); if (!rtpengine_hash_table) { @@ -51,15 +60,18 @@ int rtpengine_hash_table_init() { return 0; } - // init hashtable entry_list heads (never filled) - for (i = 0; i < RTPENGINE_HASH_TABLE_SIZE; i++) { + // init hashtable entry_list + rtpengine_hash_table->entry_list = shm_malloc(hash_table_size * sizeof(struct rtpengine_hash_entry)); + + // init hashtable entry_list[i] (head never filled) + for (i = 0; i < hash_table_size; i++) { rtpengine_hash_table->entry_list[i] = shm_malloc(sizeof(struct rtpengine_hash_entry)); if (!rtpengine_hash_table->entry_list[i]) { LM_ERR("no shm left to create rtpengine_hash_table->entry_list[%d]\n", i); return 0; } - /* never expire the head of the hashtable index lists */ + // never expire the head of the hashtable index lists rtpengine_hash_table->entry_list[i]->tout = -1; rtpengine_hash_table->entry_list[i]->next = NULL; } @@ -84,9 +96,9 @@ int rtpengine_hash_table_destroy() { return 0; } - // destroy hashtable entry_list content + // destroy hashtable entry_list[i] lock_get(rtpengine_hash_lock); - for (i = 0; i < RTPENGINE_HASH_TABLE_SIZE; i++) { + for (i = 0; i < hash_table_size; i++) { entry = rtpengine_hash_table->entry_list[i]; while (entry) { last_entry = entry; @@ -96,6 +108,9 @@ int rtpengine_hash_table_destroy() { } } + // destroy hashtable entry_list + shm_free(rtpengine_hash_table->entry_list); + // destroy hashtable shm_free(rtpengine_hash_table); rtpengine_hash_table = NULL; @@ -283,7 +298,7 @@ void rtpengine_hash_table_print() { lock_get(rtpengine_hash_lock); // print hashtable - for (i = 0; i < RTPENGINE_HASH_TABLE_SIZE; i++) { + for (i = 0; i < hash_table_size; i++) { entry = rtpengine_hash_table->entry_list[i]; last_entry = entry; diff --git a/modules/rtpengine/rtpengine_hash.h b/modules/rtpengine/rtpengine_hash.h index 71a73b45b1e..b0a8c739317 100644 --- a/modules/rtpengine/rtpengine_hash.h +++ b/modules/rtpengine/rtpengine_hash.h @@ -3,7 +3,6 @@ #include "../../str.h" -#define RTPENGINE_HASH_TABLE_SIZE 512 /* table entry */ struct rtpengine_hash_entry { @@ -11,16 +10,16 @@ struct rtpengine_hash_entry { str callid; // call callid struct rtpp_node *node; // call selected node - struct rtpengine_hash_entry *next; // next + struct rtpengine_hash_entry *next; // call next }; /* table */ struct rtpengine_hash_table { - struct rtpengine_hash_entry *entry_list[RTPENGINE_HASH_TABLE_SIZE]; + struct rtpengine_hash_entry **entry_list; }; -int rtpengine_hash_table_init(); +int rtpengine_hash_table_init(int size); int rtpengine_hash_table_destroy(); int rtpengine_hash_table_insert(void *key, void *value); int rtpengine_hash_table_remove(void *key); From 74fdbe2248ec79d70440bda255c2f21f801aa0f8 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Mon, 9 Nov 2015 18:04:33 +0200 Subject: [PATCH 004/142] rtpengine: kamctl fifo nh_show_hash_total Print the total number of hash entries in the hash table, at the given moment. Updated doku. --- modules/rtpengine/doc/rtpengine_admin.xml | 17 ++++++ modules/rtpengine/rtpengine.c | 64 +++++++++++++++++++---- modules/rtpengine/rtpengine_hash.c | 30 +++++++++++ modules/rtpengine/rtpengine_hash.h | 6 ++- 4 files changed, 105 insertions(+), 12 deletions(-) diff --git a/modules/rtpengine/doc/rtpengine_admin.xml b/modules/rtpengine/doc/rtpengine_admin.xml index 0c8a6477633..96a490d2ad7 100644 --- a/modules/rtpengine/doc/rtpengine_admin.xml +++ b/modules/rtpengine/doc/rtpengine_admin.xml @@ -1041,6 +1041,23 @@ $ &ctltool; fifo nh_ping_rtpp all
+ +
+ <function moreinfo="none">nh_show_hash_total</function> + + Print the total number of hash entries in the hash table at a given moment. + + + + <function moreinfo="none">nh_show_hash_total</function> usage + +... +$ &ctltool; fifo nh_show_hash_total +... + + +
+ diff --git a/modules/rtpengine/rtpengine.c b/modules/rtpengine/rtpengine.c index e48f31811e1..b3ca0110b92 100644 --- a/modules/rtpengine/rtpengine.c +++ b/modules/rtpengine/rtpengine.c @@ -109,6 +109,7 @@ MODULE_VERSION #define MI_ENABLE_RTP_PROXY "nh_enable_rtpp" #define MI_SHOW_RTP_PROXIES "nh_show_rtpp" #define MI_PING_RTP_PROXY "nh_ping_rtpp" +#define MI_SHOW_HASH_TOTAL "nh_show_hash_total" #define MI_RTP_PROXY_NOT_FOUND "RTP proxy not found" #define MI_RTP_PROXY_NOT_FOUND_LEN (sizeof(MI_RTP_PROXY_NOT_FOUND)-1) @@ -143,6 +144,10 @@ MODULE_VERSION #define MI_SUCCESS_LEN (sizeof(MI_SUCCESS)-1) #define MI_FAIL "fail" #define MI_FAIL_LEN (sizeof(MI_FAIL)-1) +#define MI_HASH_ENTRIES "entries" +#define MI_HASH_ENTRIES_LEN (sizeof(MI_HASH_ENTRIES)-1) +#define MI_HASH_ENTRIES_FAIL "Fail to get entry details" +#define MI_HASH_ENTRIES_FAIL_LEN (sizeof(MI_HASH_ENTRIES_FAIL)-1) #define MI_FOUND_ALL 2 #define MI_FOUND_ONE 1 @@ -215,12 +220,10 @@ static int rtpp_test_ping(struct rtpp_node *node); static int pv_get_rtpstat_f(struct sip_msg *, pv_param_t *, pv_value_t *); /*mi commands*/ -static struct mi_root* mi_enable_rtp_proxy(struct mi_root* cmd_tree, - void* param ); -static struct mi_root* mi_show_rtp_proxy(struct mi_root* cmd_tree, - void* param); -static struct mi_root* mi_ping_rtp_proxy(struct mi_root* cmd_tree, - void* param); +static struct mi_root* mi_enable_rtp_proxy(struct mi_root* cmd_tree, void* param); +static struct mi_root* mi_show_rtp_proxy(struct mi_root* cmd_tree, void* param); +static struct mi_root* mi_ping_rtp_proxy(struct mi_root* cmd_tree, void* param); +static struct mi_root* mi_show_hash_total(struct mi_root* cmd_tree, void* param); static int rtpengine_disable_tout = 60; @@ -350,6 +353,7 @@ static mi_export_t mi_cmds[] = { {MI_ENABLE_RTP_PROXY, mi_enable_rtp_proxy, 0, 0, 0}, {MI_SHOW_RTP_PROXIES, mi_show_rtp_proxy, 0, 0, 0}, {MI_PING_RTP_PROXY, mi_ping_rtp_proxy, 0, 0, 0}, + {MI_SHOW_HASH_TOTAL, mi_show_hash_total, 0, 0, 0}, { 0, 0, 0, 0, 0} }; @@ -1106,8 +1110,7 @@ static int add_rtpp_node_info (struct mi_node *node, return -1; } -static struct mi_root* mi_show_rtp_proxy(struct mi_root* cmd_tree, - void* param) +static struct mi_root* mi_show_rtp_proxy(struct mi_root* cmd_tree, void* param) { struct mi_node *node; struct mi_root *root = NULL; @@ -1196,8 +1199,7 @@ static struct mi_root* mi_show_rtp_proxy(struct mi_root* cmd_tree, return init_mi_tree(404, MI_ERROR, MI_ERROR_LEN); } -static struct mi_root* mi_ping_rtp_proxy(struct mi_root* cmd_tree, - void* param) +static struct mi_root* mi_ping_rtp_proxy(struct mi_root* cmd_tree, void* param) { struct mi_node *node, *crt_node; struct mi_attr *attr; @@ -1322,6 +1324,48 @@ static struct mi_root* mi_ping_rtp_proxy(struct mi_root* cmd_tree, } +static struct mi_root* mi_show_hash_total(struct mi_root* cmd_tree, void* param) +{ + struct mi_node *node, *crt_node; + struct mi_attr *attr; + struct mi_root *root = NULL; + unsigned int total; + str total_str; + + // Init print tree + root = init_mi_tree(200, MI_OK_S, MI_OK_LEN); + if (!root) { + LM_ERR("the MI tree cannot be initialized!\n"); + return 0; + } + node = &root->node; + + // Create new node and add it to the roots's kids + if(!(crt_node = add_mi_node_child(node, MI_DUP_NAME, "total", strlen("total"), 0, 0))) { + LM_ERR("cannot add the child node to the tree\n"); + goto error; + } + + // Get total number of entries + total = rtpengine_hash_table_total(); + total_str.s = int2str(total, &total_str.len); + + // Add node attributes + if ((attr = add_mi_attr(crt_node, MI_DUP_VALUE, MI_HASH_ENTRIES, MI_HASH_ENTRIES_LEN, total_str.s, total_str.len)) == 0) { + LM_ERR("cannot add attributes to the node\n"); + goto error; + } + + return root; + +error: + if (root) { + free_mi_tree(root); + } + + return init_mi_tree(404, MI_HASH_ENTRIES_FAIL, MI_HASH_ENTRIES_FAIL_LEN); +} + static int mod_init(void) diff --git a/modules/rtpengine/rtpengine_hash.c b/modules/rtpengine/rtpengine_hash.c index 3cca5749f6e..76aa144cd50 100644 --- a/modules/rtpengine/rtpengine_hash.c +++ b/modules/rtpengine/rtpengine_hash.c @@ -74,6 +74,7 @@ int rtpengine_hash_table_init(int size) { // never expire the head of the hashtable index lists rtpengine_hash_table->entry_list[i]->tout = -1; rtpengine_hash_table->entry_list[i]->next = NULL; + rtpengine_hash_table->total = 0; } // init lock @@ -165,6 +166,9 @@ int rtpengine_hash_table_insert(void *key, void *value) { // set pointers entry = last_entry; + + // update total + rtpengine_hash_table->total--; } // next entry in the list @@ -174,6 +178,9 @@ int rtpengine_hash_table_insert(void *key, void *value) { last_entry->next = new_entry; + // update total + rtpengine_hash_table->total++; + // unlock lock_release(rtpengine_hash_lock); @@ -205,6 +212,9 @@ int rtpengine_hash_table_remove(void *key) { shm_free(entry->callid.s); shm_free(entry); + // update total + rtpengine_hash_table->total--; + // unlock lock_release(rtpengine_hash_lock); @@ -222,6 +232,9 @@ int rtpengine_hash_table_remove(void *key) { // set pointers entry = last_entry; + + // update total + rtpengine_hash_table->total--; } last_entry = entry; @@ -271,6 +284,9 @@ void* rtpengine_hash_table_lookup(void *key) { // set pointers entry = last_entry; + + // update total + rtpengine_hash_table->total--; } last_entry = entry; @@ -314,6 +330,9 @@ void rtpengine_hash_table_print() { // set pointers entry = last_entry; + + // update total + rtpengine_hash_table->total--; } else { LM_DBG("hash_index=%d callid=%.*s tout=%u\n", i, entry->callid.len, entry->callid.s, entry->tout - get_ticks()); @@ -327,3 +346,14 @@ void rtpengine_hash_table_print() { // unlock lock_release(rtpengine_hash_lock); } + +unsigned int rtpengine_hash_table_total() { + + // check rtpengine hashtable + if (!rtpengine_hash_table) { + LM_ERR("NULL rtpengine_hash_table"); + return 0; + } + + return rtpengine_hash_table->total; +} diff --git a/modules/rtpengine/rtpengine_hash.h b/modules/rtpengine/rtpengine_hash.h index b0a8c739317..c9957e92199 100644 --- a/modules/rtpengine/rtpengine_hash.h +++ b/modules/rtpengine/rtpengine_hash.h @@ -15,7 +15,8 @@ struct rtpengine_hash_entry { /* table */ struct rtpengine_hash_table { - struct rtpengine_hash_entry **entry_list; + struct rtpengine_hash_entry **entry_list; // hastable + unsigned int total; // total number of entries in the hashtable }; @@ -24,6 +25,7 @@ int rtpengine_hash_table_destroy(); int rtpengine_hash_table_insert(void *key, void *value); int rtpengine_hash_table_remove(void *key); void* rtpengine_hash_table_lookup(void *key); -void rtpengine_hash_table_print() ; +void rtpengine_hash_table_print(); +unsigned int rtpengine_hash_table_total(); #endif From d75bb85c4a03dedb33004fe04c447182fdf37f5c Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Tue, 10 Nov 2015 16:04:30 +0200 Subject: [PATCH 005/142] rtpengine: Add rtpengine_allow_op modparam When the param is enabled, allow current sessions to finish and deny new sessions for manually deactivated rtpengine nodes via kamctl i.e. "disabled(permanent)" nodes. This is useful when deactivating the nodes for maintenance. Default value is 0, so the current behaviour is maintained (e.g. don't send commands to any deactivated proxy). Updated doku. --- modules/rtpengine/doc/rtpengine_admin.xml | 24 +++++++++++++++++++++++ modules/rtpengine/rtpengine.c | 19 +++++++++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/modules/rtpengine/doc/rtpengine_admin.xml b/modules/rtpengine/doc/rtpengine_admin.xml index 96a490d2ad7..34e197fa2ce 100644 --- a/modules/rtpengine/doc/rtpengine_admin.xml +++ b/modules/rtpengine/doc/rtpengine_admin.xml @@ -207,6 +207,30 @@ modparam("rtpengine", "rtpengine_disable_tout", 20) ... modparam("rtpengine", "rtpengine_tout_ms", 2000) ... + + + +
+ <varname>rtpengine_allow_op</varname> (integer) + + Enable this to allow finishing the current sessions while denying new sessions for the + manually deactivated nodes via kamctl command i.e. "disabled(permanent)" nodes. + Probably the manually deactivated machine is still running(did not crash). + + + This is useful when deactivating a node for maintanance and reject new sessions but allow current ones to finish. + + + + Default value is 0 to keep the current behaviour. + + + + Set <varname>rtpengine_allow_op</varname> parameter + +... +modparam("rtpengine", "rtpengine_allow_op", 1) +...
diff --git a/modules/rtpengine/rtpengine.c b/modules/rtpengine/rtpengine.c index b3ca0110b92..042c477da14 100644 --- a/modules/rtpengine/rtpengine.c +++ b/modules/rtpengine/rtpengine.c @@ -227,6 +227,7 @@ static struct mi_root* mi_show_hash_total(struct mi_root* cmd_tree, void* param) static int rtpengine_disable_tout = 60; +static int rtpengine_allow_op = 0; static int rtpengine_retr = 5; static int rtpengine_tout_ms = 1000; static int queried_nodes_limit = MAX_RTPP_TRIED_NODES; @@ -334,6 +335,7 @@ static param_export_t params[] = { {"rtpengine_disable_tout",INT_PARAM, &rtpengine_disable_tout }, {"rtpengine_retr", INT_PARAM, &rtpengine_retr }, {"rtpengine_tout_ms", INT_PARAM, &rtpengine_tout_ms }, + {"rtpengine_allow_op", INT_PARAM, &rtpengine_allow_op }, {"queried_nodes_limit", INT_PARAM, &queried_nodes_limit }, {"db_url", PARAM_STR, &rtpp_db_url }, {"table_name", PARAM_STR, &rtpp_table_name }, @@ -2369,7 +2371,7 @@ select_rtpp_node_new(str callid, int do_test, int op) } /* - * lookup the hastable (key=callid value=node) and get the old node + * lookup the hastable (key=callid value=node) and get the old node (e.g. for answer/delete) */ static struct rtpp_node * select_rtpp_node_old(str callid, int do_test, int op) @@ -2396,11 +2398,22 @@ select_rtpp_node_old(str callid, int do_test, int op) node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); } - // if node broke, don't send any message + // if node enabled, return it if (!node->rn_disabled) { return node; + } + + // if node _manually_ disabled(e.g kamctl) and proper configuration, return it + if (node->rn_recheck_ticks == MI_MAX_RECHECK_TICKS) { + if (rtpengine_allow_op) { + LM_DBG("node=%.*s for calllen=%d callid=%.*s is disabled(permanent) (probably still UP)! Return it\n", + node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); + return node; + } + LM_DBG("node=%.*s for calllen=%d callid=%.*s is disabled(permanent) (probably still UP)! Return NULL\n", + node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); } else { - LM_DBG("rtpengine hash table lookup find node=%.*s for calllen=%d callid=%.*s, which is disabled!\n", + LM_DBG("node=%.*s for calllen=%d callid=%.*s is disabled (probably BROKE)! Return NULL\n", node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); } From 7ad4dadcab841d191d5edc028a74cea7fe411450 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Thu, 12 Nov 2015 09:55:17 +0200 Subject: [PATCH 006/142] rtpengine: Fix comments for hastable - shm NULL checks and free already alloc'ed shm - default entry tout to 3600 sec - return node only, not the whole entry - zero shm hashtable parts - lookup and select new node if lookup fails; this is done for all commands and assures fallback behaviour - change void to struct specific - make set_rtp_inst_pvar() static -> used only in rtpengine.c - fix typos rtpproxy vs rtpengine --- modules/rtpengine/doc/rtpengine_admin.xml | 19 ++--- modules/rtpengine/rtpengine.c | 97 +++++++++++++---------- modules/rtpengine/rtpengine.h | 1 - modules/rtpengine/rtpengine_hash.c | 64 ++++++++++++--- modules/rtpengine/rtpengine_hash.h | 6 +- 5 files changed, 124 insertions(+), 63 deletions(-) diff --git a/modules/rtpengine/doc/rtpengine_admin.xml b/modules/rtpengine/doc/rtpengine_admin.xml index 34e197fa2ce..8b623c8c112 100644 --- a/modules/rtpengine/doc/rtpengine_admin.xml +++ b/modules/rtpengine/doc/rtpengine_admin.xml @@ -361,7 +361,7 @@ modparam("rtpengine", "read_sdp_pv", "$var(sdp)") route { ... $var(sdp) = $rb + "a=foo:bar\r\n"; - rtpproxy_manage(); + rtpengine_manage(); } @@ -386,7 +386,7 @@ modparam("rtpengine", "write_sdp_pv", "$avp(sdp)") ... route { ... - rtpproxy_manage(); + rtpengine_manage(); set_body("$avp(sdp)a=baz123\r\n", "application/sdp"); } @@ -406,7 +406,7 @@ route { Set <varname>rtp_inst_pvar</varname> parameter ... -modparam("rtpproxy", "rtp_inst_pvar", "$avp(RTP_INSTANCE)") +modparam("rtpengine", "rtp_inst_pvar", "$avp(RTP_INSTANCE)") ... @@ -424,7 +424,7 @@ modparam("rtpproxy", "rtp_inst_pvar", "$avp(RTP_INSTANCE)") Set <varname>hash_table_size</varname> parameter ... -modparam("rtpproxy", "hash_table_size", "123") +modparam("rtpengine", "hash_table_size", "123") ... @@ -434,23 +434,24 @@ modparam("rtpproxy", "hash_table_size", "123") <varname>hash_table_tout</varname> (integer) Number of seconds after an rtpengine hash table entry is marked for deletion. - By default, this parameter is set to 120 (seconds). + By default, this parameter is set to 3600 (seconds). To maintain information about a selected rtp machine node, for a given call, entries are added in a hashtable of (callid, node) pairs. - When "offer" comes, insert new entry in the hastable. - When subsequent commands come, lookup callid and return chosen node. - When "delete" comes, remove old entry from hashtable. + When command comes, lookup callid. If found, return chosen node. If not found, choose a new node, insert it in the hastable and return the chosen node. NOTE: In the current implementation, the actual deletion happens on the fly, while insert/remove/lookup the hastable, only for the entries in the insert/remove/lookup path. + + NOTE: When configuring this parameter, one should consider maximum call time VS share memory for unfinished calls. + Set <varname>hash_table_tout</varname> parameter ... -modparam("rtpproxy", "hash_table_tout", "300") +modparam("rtpengine", "hash_table_tout", "300") ... diff --git a/modules/rtpengine/rtpengine.c b/modules/rtpengine/rtpengine.c index 042c477da14..a11e38459bf 100644 --- a/modules/rtpengine/rtpengine.c +++ b/modules/rtpengine/rtpengine.c @@ -218,6 +218,7 @@ static int rtpp_test_ping(struct rtpp_node *node); /* Pseudo-Variables */ static int pv_get_rtpstat_f(struct sip_msg *, pv_param_t *, pv_value_t *); +static int set_rtp_inst_pvar(struct sip_msg *msg, const str * const uri); /*mi commands*/ static struct mi_root* mi_enable_rtp_proxy(struct mi_root* cmd_tree, void* param); @@ -235,7 +236,7 @@ static pid_t mypid; static unsigned int myseqn = 0; static str extra_id_pv_param = {NULL, 0}; static char *setid_avp_param = NULL; -static int hash_table_tout = 120; +static int hash_table_tout = 3600; static int hash_table_size = 256; static char ** rtpp_strings=0; @@ -2284,6 +2285,7 @@ select_rtpp_node_new(str callid, int do_test, int op) int was_forced = 0; /* XXX Use quick-and-dirty hashing algo */ + sum = 0; for(i = 0; i < callid.len; i++) sum += callid.s[i]; sum &= 0xff; @@ -2347,26 +2349,38 @@ select_rtpp_node_new(str callid, int do_test, int op) goto retry; } - /* build hash table entry */ + /* build the entry */ struct rtpengine_hash_entry *entry = shm_malloc(sizeof(struct rtpp_node)); + if (!entry) { + LM_ERR("rtpengine hash table fail to create entry for calllen=%d callid=%.*s\n", + callid.len, callid.len, callid.s); + return node; + } + + /* fill the entry */ if (shm_str_dup(&entry->callid, &callid) < 0) { - LM_ERR("rtpengine hash table fail to duplicate calllen=%d callid=%.*s", + LM_ERR("rtpengine hash table fail to duplicate calllen=%d callid=%.*s\n", callid.len, callid.len, callid.s); + shm_free(entry); + return node; } entry->node = node; entry->next = NULL; entry->tout = get_ticks() + hash_table_tout; - /* Insert the key<->entry from the hashtable */ + /* insert the key<->entry from the hashtable */ if (!rtpengine_hash_table_insert(&callid, entry)) { - LM_ERR("rtpengine hash table fail to insert node=%.*s for calllen=%d callid=%.*s", + LM_ERR("rtpengine hash table fail to insert node=%.*s for calllen=%d callid=%.*s\n", node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); + shm_free(entry->callid.s); + shm_free(entry); + return node; } else { LM_DBG("rtpengine hash table insert node=%.*s for calllen=%d callid=%.*s\n", node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); } - /* Return selected node */ + /* return selected node */ return node; } @@ -2377,20 +2391,11 @@ static struct rtpp_node * select_rtpp_node_old(str callid, int do_test, int op) { struct rtpp_node *node = NULL; - struct rtpengine_hash_entry *entry = NULL; - entry = rtpengine_hash_table_lookup(&callid); - if (!entry) { - LM_ERR("rtpengine hash table lookup failed to find entry for calllen=%d callid=%.*s\n", - callid.len, callid.len, callid.s); - } else { - LM_DBG("rtpengine hash table lookup find entry for calllen=%d callid=%.*s\n", - callid.len, callid.len, callid.s); - node = entry->node; - } + node = rtpengine_hash_table_lookup(&callid); if (!node) { - LM_ERR("rtpengine hash table lookup failed to find node for calllen=%d callid=%.*s\n", + LM_NOTICE("rtpengine hash table lookup failed to find node for calllen=%d callid=%.*s\n", callid.len, callid.len, callid.s); return NULL; } else { @@ -2398,6 +2403,39 @@ select_rtpp_node_old(str callid, int do_test, int op) node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); } + return node; +} + +/* + * Main balancing routine. This DO try to keep the same proxy for + * the call if some proxies were disabled or enabled (e.g. kamctl command) + */ +static struct rtpp_node * +select_rtpp_node(str callid, int do_test, int op) +{ + struct rtpp_node *node = NULL; + + if(!active_rtpp_set) { + LM_ERR("script error - no valid set selected\n"); + return NULL; + } + + // lookup node + node = select_rtpp_node_old(callid, do_test, op); + + // check node + if (!node) { + // run the selection algorithm + node = select_rtpp_node_new(callid, do_test, op); + + // check node + if (!node) { + LM_ERR("rtpengine failed to select new for calllen=%d callid=%.*s\n", + callid.len, callid.len, callid.s); + return NULL; + } + } + // if node enabled, return it if (!node->rn_disabled) { return node; @@ -2420,28 +2458,6 @@ select_rtpp_node_old(str callid, int do_test, int op) return NULL; } -/* - * Main balancing routine. This DO try to keep the same proxy for - * the call if some proxies were disabled or enabled (e.g. kamctl command) - */ -static struct rtpp_node * -select_rtpp_node(str callid, int do_test, int op) -{ - if(!active_rtpp_set) { - LM_ERR("script error - no valid set selected\n"); - return NULL; - } - - // calculate and choose a node - if (op == OP_OFFER) { - // run the selection algorithm - return select_rtpp_node_new(callid, do_test, op); - } else { - // lookup the hastable (key=callid value=node) and get the old node - return select_rtpp_node_old(callid, do_test, op); - } -} - static int get_extra_id(struct sip_msg* msg, str *id_str) { if(msg==NULL || extra_id_pv==NULL || id_str==NULL) { @@ -2858,7 +2874,8 @@ pv_get_rtpstat_f(struct sip_msg *msg, pv_param_t *param, return rtpengine_rtpp_set_wrap(msg, rtpengine_rtpstat_wrap, parms, 1); } -int set_rtp_inst_pvar(struct sip_msg *msg, const str * const uri) { +static int +set_rtp_inst_pvar(struct sip_msg *msg, const str * const uri) { pv_value_t val; if (rtp_inst_pvar == NULL) diff --git a/modules/rtpengine/rtpengine.h b/modules/rtpengine/rtpengine.h index af61701550d..71ce2645485 100644 --- a/modules/rtpengine/rtpengine.h +++ b/modules/rtpengine/rtpengine.h @@ -61,7 +61,6 @@ struct rtpp_set_head{ struct rtpp_set *get_rtpp_set(int set_id); int add_rtpengine_socks(struct rtpp_set * rtpp_list, char * rtpproxy); -int set_rtp_inst_pvar(struct sip_msg *msg, const str * const uri); int init_rtpproxy_db(void); diff --git a/modules/rtpengine/rtpengine_hash.c b/modules/rtpengine/rtpengine_hash.c index 76aa144cd50..566a9607eda 100644 --- a/modules/rtpengine/rtpengine_hash.c +++ b/modules/rtpengine/rtpengine_hash.c @@ -22,13 +22,12 @@ static int str_cmp_str(const str *a, const str *b) { } /* from sipwise rtpengine */ -static int str_equal(void *a, void *b) { - return (str_cmp_str((str *) a, (str *) b) == 0); +static int str_equal(str *a, str *b) { + return (str_cmp_str(a, b) == 0); } /* from sipwise rtpengine */ -static unsigned int str_hash(void *ss) { - const str *s = (str*) ss; +static unsigned int str_hash(str *s) { unsigned int ret = 5381; str it = *s; @@ -62,14 +61,22 @@ int rtpengine_hash_table_init(int size) { // init hashtable entry_list rtpengine_hash_table->entry_list = shm_malloc(hash_table_size * sizeof(struct rtpengine_hash_entry)); + if (!rtpengine_hash_table->entry_list) { + LM_ERR("no shm left to create rtpengine_hash_table->entry_list\n"); + rtpengine_hash_table_destroy(); + return 0; + } + memset(rtpengine_hash_table->entry_list, 0, hash_table_size * sizeof(struct rtpengine_hash_entry)); - // init hashtable entry_list[i] (head never filled) + // init hashtable entry_list[i] (head never filled); destroy table on error for (i = 0; i < hash_table_size; i++) { rtpengine_hash_table->entry_list[i] = shm_malloc(sizeof(struct rtpengine_hash_entry)); if (!rtpengine_hash_table->entry_list[i]) { LM_ERR("no shm left to create rtpengine_hash_table->entry_list[%d]\n", i); + rtpengine_hash_table_destroy(); return 0; } + memset(rtpengine_hash_table->entry_list[i], 0, sizeof(struct rtpengine_hash_entry)); // never expire the head of the hashtable index lists rtpengine_hash_table->entry_list[i]->tout = -1; @@ -81,6 +88,7 @@ int rtpengine_hash_table_init(int size) { rtpengine_hash_lock = lock_alloc(); if (!rtpengine_hash_lock) { LM_ERR("no shm left to init rtpengine_hash_table lock"); + rtpengine_hash_table_destroy(); return 0; } @@ -97,6 +105,14 @@ int rtpengine_hash_table_destroy() { return 0; } + // check rtpengine hashtable->entry_list + if (!rtpengine_hash_table->entry_list) { + LM_ERR("NULL rtpengine_hash_table->entry_list"); + shm_free(rtpengine_hash_table); + rtpengine_hash_table = NULL; + return 0; + } + // destroy hashtable entry_list[i] lock_get(rtpengine_hash_lock); for (i = 0; i < hash_table_size; i++) { @@ -111,6 +127,7 @@ int rtpengine_hash_table_destroy() { // destroy hashtable entry_list shm_free(rtpengine_hash_table->entry_list); + rtpengine_hash_table->entry_list = NULL; // destroy hashtable shm_free(rtpengine_hash_table); @@ -128,7 +145,7 @@ int rtpengine_hash_table_destroy() { return 1; } -int rtpengine_hash_table_insert(void *key, void *value) { +int rtpengine_hash_table_insert(str *key, struct rtpengine_hash_entry *value) { struct rtpengine_hash_entry *entry, *last_entry; struct rtpengine_hash_entry *new_entry = (struct rtpengine_hash_entry *) value; unsigned int hash_index; @@ -139,6 +156,12 @@ int rtpengine_hash_table_insert(void *key, void *value) { return 0; } + // check rtpengine hashtable->entry_list + if (!rtpengine_hash_table->entry_list) { + LM_ERR("NULL rtpengine_hash_table->entry_list"); + return 0; + } + // get entry list hash_index = str_hash(key); entry = rtpengine_hash_table->entry_list[hash_index]; @@ -187,7 +210,7 @@ int rtpengine_hash_table_insert(void *key, void *value) { return 1; } -int rtpengine_hash_table_remove(void *key) { +int rtpengine_hash_table_remove(str *key) { struct rtpengine_hash_entry *entry, *last_entry; unsigned int hash_index; @@ -197,6 +220,12 @@ int rtpengine_hash_table_remove(void *key) { return 0; } + // check rtpengine hashtable->entry_list + if (!rtpengine_hash_table->entry_list) { + LM_ERR("NULL rtpengine_hash_table->entry_list"); + return 0; + } + // get first entry from entry list; jump over unused list head hash_index = str_hash(key); entry = rtpengine_hash_table->entry_list[hash_index]; @@ -247,14 +276,21 @@ int rtpengine_hash_table_remove(void *key) { return 0; } -void* rtpengine_hash_table_lookup(void *key) { +struct rtpp_node *rtpengine_hash_table_lookup(str *key) { struct rtpengine_hash_entry *entry, *last_entry; unsigned int hash_index; + struct rtpp_node *node; // check rtpengine hashtable if (!rtpengine_hash_table) { LM_ERR("NULL rtpengine_hash_table"); - return 0; + return NULL; + } + + // check rtpengine hashtable->entry_list + if (!rtpengine_hash_table->entry_list) { + LM_ERR("NULL rtpengine_hash_table->entry_list"); + return NULL; } // get first entry from entry list; jump over unused list head @@ -267,10 +303,12 @@ void* rtpengine_hash_table_lookup(void *key) { while (entry) { // if key found, return entry if (str_equal(&entry->callid, (str *)key)) { + node = entry->node; + // unlock lock_release(rtpengine_hash_lock); - return entry; + return node; } // if expired entry discovered, delete it @@ -310,6 +348,12 @@ void rtpengine_hash_table_print() { return ; } + // check rtpengine hashtable->entry_list + if (!rtpengine_hash_table->entry_list) { + LM_ERR("NULL rtpengine_hash_table->entry_list"); + return ; + } + // lock lock_get(rtpengine_hash_lock); diff --git a/modules/rtpengine/rtpengine_hash.h b/modules/rtpengine/rtpengine_hash.h index c9957e92199..c0a9ed8c6bc 100644 --- a/modules/rtpengine/rtpengine_hash.h +++ b/modules/rtpengine/rtpengine_hash.h @@ -22,9 +22,9 @@ struct rtpengine_hash_table { int rtpengine_hash_table_init(int size); int rtpengine_hash_table_destroy(); -int rtpengine_hash_table_insert(void *key, void *value); -int rtpengine_hash_table_remove(void *key); -void* rtpengine_hash_table_lookup(void *key); +int rtpengine_hash_table_insert(str *key, struct rtpengine_hash_entry *value); +int rtpengine_hash_table_remove(str *key); +struct rtpp_node *rtpengine_hash_table_lookup(str *key); void rtpengine_hash_table_print(); unsigned int rtpengine_hash_table_total(); From 5f936a387fae32f4a4f7c11a9cbd5666b31ef9e7 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Mon, 16 Nov 2015 10:49:36 +0200 Subject: [PATCH 007/142] rtpengine: Fix deletion for branching scenarios - hash table entry contains callid, viabranch - hash table lookup based on callid, viabranch (useful for branching scenarios); keep doing the hash table remove right away - remove op param when select_rtpp_node(); not needed --- modules/rtpengine/rtpengine.c | 69 +++++++++-------- modules/rtpengine/rtpengine_hash.c | 116 +++++++++++++++++++---------- modules/rtpengine/rtpengine_hash.h | 12 ++- 3 files changed, 121 insertions(+), 76 deletions(-) diff --git a/modules/rtpengine/rtpengine.c b/modules/rtpengine/rtpengine.c index a11e38459bf..7fa328365f8 100644 --- a/modules/rtpengine/rtpengine.c +++ b/modules/rtpengine/rtpengine.c @@ -193,9 +193,9 @@ static int rtpengine_offer_answer(struct sip_msg *msg, const char *flags, int op static int fixup_set_id(void ** param, int param_no); static int set_rtpengine_set_f(struct sip_msg * msg, char * str1, char * str2); static struct rtpp_set * select_rtpp_set(int id_set); -static struct rtpp_node *select_rtpp_node_new(str, int, int); -static struct rtpp_node *select_rtpp_node_old(str, int, int); -static struct rtpp_node *select_rtpp_node(str, int, int); +static struct rtpp_node *select_rtpp_node_new(str, str, int); +static struct rtpp_node *select_rtpp_node_old(str, str, int); +static struct rtpp_node *select_rtpp_node(str, str, int); static char *send_rtpp_command(struct rtpp_node *, bencode_item_t *, int *); static int get_extra_id(struct sip_msg* msg, str *id_str); @@ -1859,7 +1859,8 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_ { struct ng_flags_parse ng_flags; bencode_item_t *item, *resp; - str callid, from_tag, to_tag, body, viabranch, error; + str callid = STR_NULL, from_tag = STR_NULL, to_tag = STR_NULL, viabranch = STR_NULL; + str body = STR_NULL, error = STR_NULL; int ret, queried_nodes; struct rtpp_node *node; char *cp; @@ -1992,7 +1993,7 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_ LM_ERR("queried nodes limit reached\n"); goto error; } - node = select_rtpp_node(callid, 1, op); + node = select_rtpp_node(callid, viabranch, 1); if (!node) { LM_ERR("no available proxies\n"); goto error; @@ -2036,12 +2037,12 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_ if (op == OP_DELETE) { /* Delete the key<->value from the hashtable */ - if (!rtpengine_hash_table_remove(&callid)) { - LM_ERR("rtpengine hash table failed to remove entry for callen=%d callid=%.*s\n", - callid.len, callid.len, callid.s); + if (!rtpengine_hash_table_remove(callid, viabranch)) { + LM_ERR("rtpengine hash table failed to remove entry for callen=%d callid=%.*s viabranch=%.*s\n", + callid.len, callid.len, callid.s, viabranch.len, viabranch.s); } else { - LM_DBG("rtpengine hash table remove entry for callen=%d callid=%.*s\n", - callid.len, callid.len, callid.s); + LM_DBG("rtpengine hash table remove entry for callen=%d callid=%.*s viabranch=%.*s\n", + callid.len, callid.len, callid.s, viabranch.len, viabranch.s); } } @@ -2278,7 +2279,7 @@ static struct rtpp_set * select_rtpp_set(int id_set ){ * run the selection algorithm and return the new selected node */ static struct rtpp_node * -select_rtpp_node_new(str callid, int do_test, int op) +select_rtpp_node_new(str callid, str viabranch, int do_test) { struct rtpp_node* node; unsigned i, sum, sumcut, weight_sum; @@ -2350,18 +2351,25 @@ select_rtpp_node_new(str callid, int do_test, int op) } /* build the entry */ - struct rtpengine_hash_entry *entry = shm_malloc(sizeof(struct rtpp_node)); + struct rtpengine_hash_entry *entry = shm_malloc(sizeof(struct rtpengine_hash_entry)); if (!entry) { - LM_ERR("rtpengine hash table fail to create entry for calllen=%d callid=%.*s\n", - callid.len, callid.len, callid.s); + LM_ERR("rtpengine hash table fail to create entry for calllen=%d callid=%.*s viabranch=%.*s\n", + callid.len, callid.len, callid.s, viabranch.len, viabranch.s); return node; } + memset(entry, 0, sizeof(struct rtpengine_hash_entry)); /* fill the entry */ if (shm_str_dup(&entry->callid, &callid) < 0) { LM_ERR("rtpengine hash table fail to duplicate calllen=%d callid=%.*s\n", callid.len, callid.len, callid.s); - shm_free(entry); + rtpengine_hash_table_free_entry(entry); + return node; + } + if (shm_str_dup(&entry->viabranch, &viabranch) < 0) { + LM_ERR("rtpengine hash table fail to duplicate calllen=%d viabranch=%.*s\n", + callid.len, viabranch.len, viabranch.s); + rtpengine_hash_table_free_entry(entry); return node; } entry->node = node; @@ -2369,15 +2377,14 @@ select_rtpp_node_new(str callid, int do_test, int op) entry->tout = get_ticks() + hash_table_tout; /* insert the key<->entry from the hashtable */ - if (!rtpengine_hash_table_insert(&callid, entry)) { - LM_ERR("rtpengine hash table fail to insert node=%.*s for calllen=%d callid=%.*s\n", - node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); - shm_free(entry->callid.s); - shm_free(entry); + if (!rtpengine_hash_table_insert(callid, viabranch, entry)) { + LM_ERR("rtpengine hash table fail to insert node=%.*s for calllen=%d callid=%.*s viabranch=%.*s\n", + node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s, viabranch.len, viabranch.s); + rtpengine_hash_table_free_entry(entry); return node; } else { - LM_DBG("rtpengine hash table insert node=%.*s for calllen=%d callid=%.*s\n", - node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); + LM_DBG("rtpengine hash table insert node=%.*s for calllen=%d callid=%.*s viabranch=%.*s\n", + node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s, viabranch.len, viabranch.s); } /* return selected node */ @@ -2388,19 +2395,19 @@ select_rtpp_node_new(str callid, int do_test, int op) * lookup the hastable (key=callid value=node) and get the old node (e.g. for answer/delete) */ static struct rtpp_node * -select_rtpp_node_old(str callid, int do_test, int op) +select_rtpp_node_old(str callid, str viabranch, int do_test) { struct rtpp_node *node = NULL; - node = rtpengine_hash_table_lookup(&callid); + node = rtpengine_hash_table_lookup(callid, viabranch); if (!node) { - LM_NOTICE("rtpengine hash table lookup failed to find node for calllen=%d callid=%.*s\n", - callid.len, callid.len, callid.s); + LM_NOTICE("rtpengine hash table lookup failed to find node for calllen=%d callid=%.*s viabranch=%.*s\n", + callid.len, callid.len, callid.s, viabranch.len, viabranch.s); return NULL; } else { - LM_DBG("rtpengine hash table lookup find node=%.*s for calllen=%d callid=%.*s\n", - node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); + LM_DBG("rtpengine hash table lookup find node=%.*s for calllen=%d callid=%.*s viabranch=%.*s\n", + node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s, viabranch.len, viabranch.s); } return node; @@ -2411,7 +2418,7 @@ select_rtpp_node_old(str callid, int do_test, int op) * the call if some proxies were disabled or enabled (e.g. kamctl command) */ static struct rtpp_node * -select_rtpp_node(str callid, int do_test, int op) +select_rtpp_node(str callid, str viabranch, int do_test) { struct rtpp_node *node = NULL; @@ -2421,12 +2428,12 @@ select_rtpp_node(str callid, int do_test, int op) } // lookup node - node = select_rtpp_node_old(callid, do_test, op); + node = select_rtpp_node_old(callid, viabranch, do_test); // check node if (!node) { // run the selection algorithm - node = select_rtpp_node_new(callid, do_test, op); + node = select_rtpp_node_new(callid, viabranch, do_test); // check node if (!node) { diff --git a/modules/rtpengine/rtpengine_hash.c b/modules/rtpengine/rtpengine_hash.c index 566a9607eda..027fd8a26f0 100644 --- a/modules/rtpengine/rtpengine_hash.c +++ b/modules/rtpengine/rtpengine_hash.c @@ -11,25 +11,25 @@ static struct rtpengine_hash_table *rtpengine_hash_table; static int hash_table_size; /* from sipwise rtpengine */ -static int str_cmp_str(const str *a, const str *b) { - if (a->len < b->len) +static int str_cmp_str(const str a, const str b) { + if (a.len < b.len) return -1; - if (a->len > b->len) + if (a.len > b.len) return 1; - if (a->len == 0 && b->len == 0) + if (a.len == 0 && b.len == 0) return 0; - return memcmp(a->s, b->s, a->len); + return memcmp(a.s, b.s, a.len); } /* from sipwise rtpengine */ -static int str_equal(str *a, str *b) { +static int str_equal(str a, str b) { return (str_cmp_str(a, b) == 0); } /* from sipwise rtpengine */ -static unsigned int str_hash(str *s) { +static unsigned int str_hash(str s) { unsigned int ret = 5381; - str it = *s; + str it = s; while (it.len > 0) { ret = (ret << 5) + ret + *it.s; @@ -40,7 +40,7 @@ static unsigned int str_hash(str *s) { return ret % hash_table_size; } -/* rtpengine glib hash API */ +/* rtpengine hash API */ int rtpengine_hash_table_init(int size) { int i; @@ -58,6 +58,7 @@ int rtpengine_hash_table_init(int size) { LM_ERR("no shm left to create rtpengine_hash_table\n"); return 0; } + memset(rtpengine_hash_table, 0, sizeof(struct rtpengine_hash_table)); // init hashtable entry_list rtpengine_hash_table->entry_list = shm_malloc(hash_table_size * sizeof(struct rtpengine_hash_entry)); @@ -97,7 +98,6 @@ int rtpengine_hash_table_init(int size) { int rtpengine_hash_table_destroy() { int i; - struct rtpengine_hash_entry *entry, *last_entry; // check rtpengine hashtable if (!rtpengine_hash_table) { @@ -113,16 +113,11 @@ int rtpengine_hash_table_destroy() { return 0; } - // destroy hashtable entry_list[i] lock_get(rtpengine_hash_lock); + + // destroy hashtable entry_list[i] for (i = 0; i < hash_table_size; i++) { - entry = rtpengine_hash_table->entry_list[i]; - while (entry) { - last_entry = entry; - entry = entry->next; - shm_free(last_entry->callid.s); - shm_free(last_entry); - } + rtpengine_hash_table_free_entry_list(rtpengine_hash_table->entry_list[i]); } // destroy hashtable entry_list @@ -132,6 +127,7 @@ int rtpengine_hash_table_destroy() { // destroy hashtable shm_free(rtpengine_hash_table); rtpengine_hash_table = NULL; + lock_release(rtpengine_hash_lock); // destroy lock @@ -145,7 +141,7 @@ int rtpengine_hash_table_destroy() { return 1; } -int rtpengine_hash_table_insert(str *key, struct rtpengine_hash_entry *value) { +int rtpengine_hash_table_insert(str callid, str viabranch, struct rtpengine_hash_entry *value) { struct rtpengine_hash_entry *entry, *last_entry; struct rtpengine_hash_entry *new_entry = (struct rtpengine_hash_entry *) value; unsigned int hash_index; @@ -163,18 +159,21 @@ int rtpengine_hash_table_insert(str *key, struct rtpengine_hash_entry *value) { } // get entry list - hash_index = str_hash(key); + hash_index = str_hash(callid); entry = rtpengine_hash_table->entry_list[hash_index]; last_entry = entry; // lock lock_get(rtpengine_hash_lock); while (entry) { - // if key found, don't add new entry - if (str_equal(&entry->callid, &new_entry->callid)) { + // if found, don't add new entry + if (str_equal(entry->callid, new_entry->callid) && + str_equal(entry->viabranch, new_entry->viabranch)) { // unlock lock_release(rtpengine_hash_lock); - LM_ERR("Call id %.*s already in hashtable, ignore new value", entry->callid.len, entry->callid.s); + LM_NOTICE("callid=%.*s, viabranch=%.*s already in hashtable, ignore new value", + entry->callid.len, entry->callid.s, + entry->viabranch.len, entry->viabranch.s); return 0; } @@ -184,8 +183,7 @@ int rtpengine_hash_table_insert(str *key, struct rtpengine_hash_entry *value) { last_entry->next = entry->next; // free current entry; entry points to unknown - shm_free(entry->callid.s); - shm_free(entry); + rtpengine_hash_table_free_entry(entry); // set pointers entry = last_entry; @@ -210,7 +208,7 @@ int rtpengine_hash_table_insert(str *key, struct rtpengine_hash_entry *value) { return 1; } -int rtpengine_hash_table_remove(str *key) { +int rtpengine_hash_table_remove(str callid, str viabranch) { struct rtpengine_hash_entry *entry, *last_entry; unsigned int hash_index; @@ -227,19 +225,19 @@ int rtpengine_hash_table_remove(str *key) { } // get first entry from entry list; jump over unused list head - hash_index = str_hash(key); + hash_index = str_hash(callid); entry = rtpengine_hash_table->entry_list[hash_index]; last_entry = entry; // lock lock_get(rtpengine_hash_lock); while (entry) { - // if key found, delete entry - if (str_equal(&entry->callid, (str *)key)) { + // if callid found, delete entry + if (str_equal(entry->callid, callid) && + str_equal(entry->viabranch, viabranch)) { // free entry last_entry->next = entry->next; - shm_free(entry->callid.s); - shm_free(entry); + rtpengine_hash_table_free_entry(entry); // update total rtpengine_hash_table->total--; @@ -256,8 +254,7 @@ int rtpengine_hash_table_remove(str *key) { last_entry->next = entry->next; // free current entry; entry points to unknown - shm_free(entry->callid.s); - shm_free(entry); + rtpengine_hash_table_free_entry(entry); // set pointers entry = last_entry; @@ -276,7 +273,7 @@ int rtpengine_hash_table_remove(str *key) { return 0; } -struct rtpp_node *rtpengine_hash_table_lookup(str *key) { +struct rtpp_node *rtpengine_hash_table_lookup(str callid, str viabranch) { struct rtpengine_hash_entry *entry, *last_entry; unsigned int hash_index; struct rtpp_node *node; @@ -294,15 +291,16 @@ struct rtpp_node *rtpengine_hash_table_lookup(str *key) { } // get first entry from entry list; jump over unused list head - hash_index = str_hash(key); + hash_index = str_hash(callid); entry = rtpengine_hash_table->entry_list[hash_index]; last_entry = entry; // lock lock_get(rtpengine_hash_lock); while (entry) { - // if key found, return entry - if (str_equal(&entry->callid, (str *)key)) { + // if callid found, return entry + if (str_equal(entry->callid, callid) && + str_equal(entry->viabranch, viabranch)) { node = entry->node; // unlock @@ -317,8 +315,7 @@ struct rtpp_node *rtpengine_hash_table_lookup(str *key) { last_entry->next = entry->next; // free current entry; entry points to unknown - shm_free(entry->callid.s); - shm_free(entry); + rtpengine_hash_table_free_entry(entry); // set pointers entry = last_entry; @@ -369,8 +366,7 @@ void rtpengine_hash_table_print() { last_entry->next = entry->next; // free current entry; entry points to unknown - shm_free(entry->callid.s); - shm_free(entry); + rtpengine_hash_table_free_entry(entry); // set pointers entry = last_entry; @@ -401,3 +397,41 @@ unsigned int rtpengine_hash_table_total() { return rtpengine_hash_table->total; } + +void rtpengine_hash_table_free_entry(struct rtpengine_hash_entry *entry) { + if (!entry) { + return ; + } + + // free callid + if (entry->callid.s) { + shm_free(entry->callid.s); + } + + // free viabranch + if (entry->viabranch.s) { + shm_free(entry->viabranch.s); + } + + // free entry + shm_free(entry); + + return ; +} + +void rtpengine_hash_table_free_entry_list(struct rtpengine_hash_entry *entry_list) { + struct rtpengine_hash_entry *entry, *last_entry; + + if (!entry_list) { + return ; + } + + entry = entry_list; + while (entry) { + last_entry = entry; + entry = entry->next; + rtpengine_hash_table_free_entry(last_entry); + } + + return ; +} diff --git a/modules/rtpengine/rtpengine_hash.h b/modules/rtpengine/rtpengine_hash.h index c0a9ed8c6bc..2d1ab4545f1 100644 --- a/modules/rtpengine/rtpengine_hash.h +++ b/modules/rtpengine/rtpengine_hash.h @@ -6,10 +6,11 @@ /* table entry */ struct rtpengine_hash_entry { - unsigned int tout; // call timeout str callid; // call callid + str viabranch; // call viabranch struct rtpp_node *node; // call selected node + unsigned int tout; // call timeout struct rtpengine_hash_entry *next; // call next }; @@ -22,10 +23,13 @@ struct rtpengine_hash_table { int rtpengine_hash_table_init(int size); int rtpengine_hash_table_destroy(); -int rtpengine_hash_table_insert(str *key, struct rtpengine_hash_entry *value); -int rtpengine_hash_table_remove(str *key); -struct rtpp_node *rtpengine_hash_table_lookup(str *key); +int rtpengine_hash_table_insert(str callid, str viabranch, struct rtpengine_hash_entry *value); +int rtpengine_hash_table_remove(str callid, str viabranch); +struct rtpp_node *rtpengine_hash_table_lookup(str callid, str viabranch); void rtpengine_hash_table_print(); unsigned int rtpengine_hash_table_total(); +void rtpengine_hash_table_free_entry(struct rtpengine_hash_entry *entry); +void rtpengine_hash_table_free_entry_list(struct rtpengine_hash_entry *entry_list); + #endif From 6390e8b35da0f8ad92430e40627d2c52e0b3ca52 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Fri, 4 Dec 2015 13:08:11 +0200 Subject: [PATCH 008/142] rtpengine: Don't shm_str_dup() a NULL str->s Don't dup a NULL str->s to avoid warning message. This happened usually when viabranch is not used(default being NULL). --- modules/rtpengine/rtpengine.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/modules/rtpengine/rtpengine.c b/modules/rtpengine/rtpengine.c index 7fa328365f8..893bc9dd67f 100644 --- a/modules/rtpengine/rtpengine.c +++ b/modules/rtpengine/rtpengine.c @@ -2360,17 +2360,21 @@ select_rtpp_node_new(str callid, str viabranch, int do_test) memset(entry, 0, sizeof(struct rtpengine_hash_entry)); /* fill the entry */ - if (shm_str_dup(&entry->callid, &callid) < 0) { - LM_ERR("rtpengine hash table fail to duplicate calllen=%d callid=%.*s\n", - callid.len, callid.len, callid.s); - rtpengine_hash_table_free_entry(entry); - return node; + if (callid.s && callid.len > 0) { + if (shm_str_dup(&entry->callid, &callid) < 0) { + LM_ERR("rtpengine hash table fail to duplicate calllen=%d callid=%.*s\n", + callid.len, callid.len, callid.s); + rtpengine_hash_table_free_entry(entry); + return node; + } } - if (shm_str_dup(&entry->viabranch, &viabranch) < 0) { - LM_ERR("rtpengine hash table fail to duplicate calllen=%d viabranch=%.*s\n", - callid.len, viabranch.len, viabranch.s); - rtpengine_hash_table_free_entry(entry); - return node; + if (viabranch.s && viabranch.len > 0) { + if (shm_str_dup(&entry->viabranch, &viabranch) < 0) { + LM_ERR("rtpengine hash table fail to duplicate calllen=%d viabranch=%.*s\n", + callid.len, viabranch.len, viabranch.s); + rtpengine_hash_table_free_entry(entry); + return node; + } } entry->node = node; entry->next = NULL; From 5a537506141027ca3d3ef87f49913ab628c30690 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Mon, 7 Dec 2015 13:30:02 +0200 Subject: [PATCH 009/142] rtpengine: Allow op for all deactivated machines If allow_op modparam enabled, send commands to the disabled machines for the existing call. So far this was done only for manually deactivated machines. This is useful because there might be cases of proxy timeout, cases when you may want to still allow the operations for the existing calls. --- modules/rtpengine/rtpengine.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/modules/rtpengine/rtpengine.c b/modules/rtpengine/rtpengine.c index 893bc9dd67f..bba10efc4b7 100644 --- a/modules/rtpengine/rtpengine.c +++ b/modules/rtpengine/rtpengine.c @@ -2452,18 +2452,16 @@ select_rtpp_node(str callid, str viabranch, int do_test) return node; } - // if node _manually_ disabled(e.g kamctl) and proper configuration, return it - if (node->rn_recheck_ticks == MI_MAX_RECHECK_TICKS) { - if (rtpengine_allow_op) { + // if proper configuration and node manually or timeout disabled, return it + if (rtpengine_allow_op) { + if (node->rn_recheck_ticks == MI_MAX_RECHECK_TICKS) { LM_DBG("node=%.*s for calllen=%d callid=%.*s is disabled(permanent) (probably still UP)! Return it\n", node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); - return node; + } else { + LM_DBG("node=%.*s for calllen=%d callid=%.*s is disabled, either broke or timeout disabled! Return it\n", + node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); } - LM_DBG("node=%.*s for calllen=%d callid=%.*s is disabled(permanent) (probably still UP)! Return NULL\n", - node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); - } else { - LM_DBG("node=%.*s for calllen=%d callid=%.*s is disabled (probably BROKE)! Return NULL\n", - node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s); + return node; } return NULL; From 250c7125613fc0fc26b72f68a7d0bd63a4a1b430 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 7 Dec 2015 22:23:41 +0100 Subject: [PATCH 010/142] db_mysql: if autoreconnect is set, then attemt 3 times if mysql ping fails - it should help stalled/broken mysql tls connections to recover --- modules/db_mysql/km_dbase.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/db_mysql/km_dbase.c b/modules/db_mysql/km_dbase.c index 9b220c3650e..2b3d1c9bc9e 100644 --- a/modules/db_mysql/km_dbase.c +++ b/modules/db_mysql/km_dbase.c @@ -80,9 +80,13 @@ static int db_mysql_submit_query(const db1_con_t* _h, const str* _s) if (my_ping_interval) { t = time(0); if ((t - CON_TIMESTAMP(_h)) > my_ping_interval) { - if (mysql_ping(CON_CONNECTION(_h))) { - LM_WARN("driver error on ping: %s\n", mysql_error(CON_CONNECTION(_h))); - counter_inc(mysql_cnts_h.driver_err); + for (i=0; i < (db_mysql_auto_reconnect ? 3 : 1); i++) { + if (mysql_ping(CON_CONNECTION(_h))) { + LM_WARN("driver error on ping: %s\n", mysql_error(CON_CONNECTION(_h))); + counter_inc(mysql_cnts_h.driver_err); + } else { + break; + } } } /* From a22b59fc802c1c1ee2a13ed772c515398f41e0a7 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Tue, 8 Dec 2015 15:29:09 +0200 Subject: [PATCH 011/142] rtpengine: Add per rows hash table locks This will further increase rtpengine's hash table access. --- modules/rtpengine/rtpengine_hash.c | 139 ++++++++++++++++++++--------- modules/rtpengine/rtpengine_hash.h | 4 + 2 files changed, 100 insertions(+), 43 deletions(-) diff --git a/modules/rtpengine/rtpengine_hash.c b/modules/rtpengine/rtpengine_hash.c index 027fd8a26f0..e20b5643b5e 100644 --- a/modules/rtpengine/rtpengine_hash.c +++ b/modules/rtpengine/rtpengine_hash.c @@ -6,7 +6,6 @@ #include "../../locking.h" #include "../../timer.h" -static gen_lock_t *rtpengine_hash_lock; static struct rtpengine_hash_table *rtpengine_hash_table; static int hash_table_size; @@ -85,14 +84,24 @@ int rtpengine_hash_table_init(int size) { rtpengine_hash_table->total = 0; } - // init lock - rtpengine_hash_lock = lock_alloc(); - if (!rtpengine_hash_lock) { - LM_ERR("no shm left to init rtpengine_hash_table lock"); + // init hashtable row_locks + rtpengine_hash_table->row_locks = shm_malloc(hash_table_size * sizeof(gen_lock_t*)); + if (!rtpengine_hash_table->row_locks) { + LM_ERR("no shm left to create rtpengine_hash_table->row_locks\n"); rtpengine_hash_table_destroy(); return 0; } + // init hashtable row_locks[i] + for (i = 0; i < hash_table_size; i++) { + rtpengine_hash_table->row_locks[i] = lock_alloc(); + if (!rtpengine_hash_table->row_locks[i]) { + LM_ERR("no shm left to create rtpengine_hash_table->row_locks[%d]\n", i); + rtpengine_hash_table_destroy(); + return 0; + } + } + return 1; } @@ -101,43 +110,47 @@ int rtpengine_hash_table_destroy() { // check rtpengine hashtable if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table"); + LM_ERR("NULL rtpengine_hash_table\n"); return 0; } // check rtpengine hashtable->entry_list if (!rtpengine_hash_table->entry_list) { - LM_ERR("NULL rtpengine_hash_table->entry_list"); + LM_ERR("NULL rtpengine_hash_table->entry_list\n"); shm_free(rtpengine_hash_table); rtpengine_hash_table = NULL; return 0; } - lock_get(rtpengine_hash_lock); - - // destroy hashtable entry_list[i] + // destroy hashtable content for (i = 0; i < hash_table_size; i++) { + // destroy hashtable entry_list[i] + if (rtpengine_hash_table->row_locks[i]) { + lock_get(rtpengine_hash_table->row_locks[i]); + } else { + LM_ERR("NULL rtpengine_hash_table->row_locks[%d]\n", i); + return 0; + } rtpengine_hash_table_free_entry_list(rtpengine_hash_table->entry_list[i]); + lock_release(rtpengine_hash_table->row_locks[i]); + + // destroy hashtable row_locks[i] + rtpengine_hash_table_free_row_lock(rtpengine_hash_table->row_locks[i]); + rtpengine_hash_table->row_locks[i] = NULL; } // destroy hashtable entry_list shm_free(rtpengine_hash_table->entry_list); rtpengine_hash_table->entry_list = NULL; + // destroy hashtable row_locks + shm_free(rtpengine_hash_table->row_locks); + rtpengine_hash_table->row_locks = NULL; + // destroy hashtable shm_free(rtpengine_hash_table); rtpengine_hash_table = NULL; - lock_release(rtpengine_hash_lock); - - // destroy lock - if (!rtpengine_hash_lock) { - LM_ERR("NULL rtpengine_hash_lock"); - } else { - lock_dealloc(rtpengine_hash_lock); - rtpengine_hash_lock = NULL; - } - return 1; } @@ -148,13 +161,19 @@ int rtpengine_hash_table_insert(str callid, str viabranch, struct rtpengine_hash // check rtpengine hashtable if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table"); + LM_ERR("NULL rtpengine_hash_table\n"); return 0; } // check rtpengine hashtable->entry_list if (!rtpengine_hash_table->entry_list) { - LM_ERR("NULL rtpengine_hash_table->entry_list"); + LM_ERR("NULL rtpengine_hash_table->entry_list\n"); + return 0; + } + + // check rtpengine hashtable->row_locks + if (!rtpengine_hash_table->row_locks) { + LM_ERR("NULL rtpengine_hash_table->row_locks\n"); return 0; } @@ -163,15 +182,21 @@ int rtpengine_hash_table_insert(str callid, str viabranch, struct rtpengine_hash entry = rtpengine_hash_table->entry_list[hash_index]; last_entry = entry; + if (rtpengine_hash_table->row_locks[hash_index]) { + lock_get(rtpengine_hash_table->row_locks[hash_index]); + } else { + LM_ERR("NULL rtpengine_hash_table->row_locks[%d]\n", hash_index); + return 0; + } + // lock - lock_get(rtpengine_hash_lock); while (entry) { // if found, don't add new entry if (str_equal(entry->callid, new_entry->callid) && str_equal(entry->viabranch, new_entry->viabranch)) { // unlock - lock_release(rtpengine_hash_lock); - LM_NOTICE("callid=%.*s, viabranch=%.*s already in hashtable, ignore new value", + lock_release(rtpengine_hash_table->row_locks[hash_index]); + LM_NOTICE("callid=%.*s, viabranch=%.*s already in hashtable, ignore new value\n", entry->callid.len, entry->callid.s, entry->viabranch.len, entry->viabranch.s); return 0; @@ -203,7 +228,7 @@ int rtpengine_hash_table_insert(str callid, str viabranch, struct rtpengine_hash rtpengine_hash_table->total++; // unlock - lock_release(rtpengine_hash_lock); + lock_release(rtpengine_hash_table->row_locks[hash_index]); return 1; } @@ -214,13 +239,13 @@ int rtpengine_hash_table_remove(str callid, str viabranch) { // check rtpengine hashtable if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table"); + LM_ERR("NULL rtpengine_hash_table\n"); return 0; } // check rtpengine hashtable->entry_list if (!rtpengine_hash_table->entry_list) { - LM_ERR("NULL rtpengine_hash_table->entry_list"); + LM_ERR("NULL rtpengine_hash_table->entry_list\n"); return 0; } @@ -230,7 +255,12 @@ int rtpengine_hash_table_remove(str callid, str viabranch) { last_entry = entry; // lock - lock_get(rtpengine_hash_lock); + if (rtpengine_hash_table->row_locks[hash_index]) { + lock_get(rtpengine_hash_table->row_locks[hash_index]); + } else { + LM_ERR("NULL rtpengine_hash_table->row_locks[%d]\n", hash_index); + return 0; + } while (entry) { // if callid found, delete entry if (str_equal(entry->callid, callid) && @@ -243,7 +273,7 @@ int rtpengine_hash_table_remove(str callid, str viabranch) { rtpengine_hash_table->total--; // unlock - lock_release(rtpengine_hash_lock); + lock_release(rtpengine_hash_table->row_locks[hash_index]); return 1; } @@ -268,7 +298,7 @@ int rtpengine_hash_table_remove(str callid, str viabranch) { } // unlock - lock_release(rtpengine_hash_lock); + lock_release(rtpengine_hash_table->row_locks[hash_index]); return 0; } @@ -280,13 +310,13 @@ struct rtpp_node *rtpengine_hash_table_lookup(str callid, str viabranch) { // check rtpengine hashtable if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table"); + LM_ERR("NULL rtpengine_hash_table\n"); return NULL; } // check rtpengine hashtable->entry_list if (!rtpengine_hash_table->entry_list) { - LM_ERR("NULL rtpengine_hash_table->entry_list"); + LM_ERR("NULL rtpengine_hash_table->entry_list\n"); return NULL; } @@ -296,7 +326,12 @@ struct rtpp_node *rtpengine_hash_table_lookup(str callid, str viabranch) { last_entry = entry; // lock - lock_get(rtpengine_hash_lock); + if (rtpengine_hash_table->row_locks[hash_index]) { + lock_get(rtpengine_hash_table->row_locks[hash_index]); + } else { + LM_ERR("NULL rtpengine_hash_table->row_locks[%d]\n", hash_index); + return 0; + } while (entry) { // if callid found, return entry if (str_equal(entry->callid, callid) && @@ -304,7 +339,7 @@ struct rtpp_node *rtpengine_hash_table_lookup(str callid, str viabranch) { node = entry->node; // unlock - lock_release(rtpengine_hash_lock); + lock_release(rtpengine_hash_table->row_locks[hash_index]); return node; } @@ -329,7 +364,7 @@ struct rtpp_node *rtpengine_hash_table_lookup(str callid, str viabranch) { } // unlock - lock_release(rtpengine_hash_lock); + lock_release(rtpengine_hash_table->row_locks[hash_index]); return NULL; } @@ -341,21 +376,27 @@ void rtpengine_hash_table_print() { // check rtpengine hashtable if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table"); + LM_ERR("NULL rtpengine_hash_table\n"); return ; } // check rtpengine hashtable->entry_list if (!rtpengine_hash_table->entry_list) { - LM_ERR("NULL rtpengine_hash_table->entry_list"); + LM_ERR("NULL rtpengine_hash_table->entry_list\n"); return ; } - // lock - lock_get(rtpengine_hash_lock); // print hashtable for (i = 0; i < hash_table_size; i++) { + // lock + if (rtpengine_hash_table->row_locks[i]) { + lock_get(rtpengine_hash_table->row_locks[i]); + } else { + LM_ERR("NULL rtpengine_hash_table->row_locks[%d]\n", i); + return ; + } + entry = rtpengine_hash_table->entry_list[i]; last_entry = entry; @@ -381,17 +422,18 @@ void rtpengine_hash_table_print() { last_entry = entry; entry = entry->next; } + + // unlock + lock_release(rtpengine_hash_table->row_locks[i]); } - // unlock - lock_release(rtpengine_hash_lock); } unsigned int rtpengine_hash_table_total() { // check rtpengine hashtable if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table"); + LM_ERR("NULL rtpengine_hash_table\n"); return 0; } @@ -431,7 +473,18 @@ void rtpengine_hash_table_free_entry_list(struct rtpengine_hash_entry *entry_lis last_entry = entry; entry = entry->next; rtpengine_hash_table_free_entry(last_entry); + last_entry = NULL; + } + + return ; +} + +void rtpengine_hash_table_free_row_lock(gen_lock_t *row_lock) { + if (!row_lock) { + return ; } + lock_destroy(row_lock); + return ; } diff --git a/modules/rtpengine/rtpengine_hash.h b/modules/rtpengine/rtpengine_hash.h index 2d1ab4545f1..c4c67baa774 100644 --- a/modules/rtpengine/rtpengine_hash.h +++ b/modules/rtpengine/rtpengine_hash.h @@ -2,6 +2,7 @@ #define _RTPENGINE_HASH_H #include "../../str.h" +#include "../../locking.h" /* table entry */ @@ -17,6 +18,7 @@ struct rtpengine_hash_entry { /* table */ struct rtpengine_hash_table { struct rtpengine_hash_entry **entry_list; // hastable + gen_lock_t **row_locks; // hastable row locks unsigned int total; // total number of entries in the hashtable }; @@ -32,4 +34,6 @@ unsigned int rtpengine_hash_table_total(); void rtpengine_hash_table_free_entry(struct rtpengine_hash_entry *entry); void rtpengine_hash_table_free_entry_list(struct rtpengine_hash_entry *entry_list); +void rtpengine_hash_table_free_row_lock(gen_lock_t *lock); + #endif From 5816e6852306c943f9b39cf8d8243201bbbdc132 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 8 Dec 2015 22:56:53 +0100 Subject: [PATCH 012/142] kamctl: updated version of the scripts --- utils/kamctl/kamctl | 2 +- utils/kamctl/kamdbctl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/kamctl/kamctl b/utils/kamctl/kamctl index 22d9643a307..974f4576072 100755 --- a/utils/kamctl/kamctl +++ b/utils/kamctl/kamctl @@ -5,7 +5,7 @@ #=================================================================== ### version for this script -VERSION='4.2.0' +VERSION='4.4.0' PATH=$PATH:/usr/local/sbin/ diff --git a/utils/kamctl/kamdbctl b/utils/kamctl/kamdbctl index e8915d14695..224111b9fb2 100755 --- a/utils/kamctl/kamdbctl +++ b/utils/kamctl/kamdbctl @@ -5,7 +5,7 @@ #=================================================================== ### version for this script -VERSION='4.2.0' +VERSION='4.4.0' PATH=$PATH:/usr/local/sbin/ From c4f2b557682b3e7172b70550913711cccf68df56 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Wed, 9 Dec 2015 11:00:15 +0200 Subject: [PATCH 013/142] rtpengine: Add per rows totals statistics For consistency with the per row locks, statistics should be also per row. --- modules/rtpengine/rtpengine_hash.c | 172 +++++++++++++++-------------- modules/rtpengine/rtpengine_hash.h | 7 +- 2 files changed, 96 insertions(+), 83 deletions(-) diff --git a/modules/rtpengine/rtpengine_hash.c b/modules/rtpengine/rtpengine_hash.c index e20b5643b5e..0062da888cc 100644 --- a/modules/rtpengine/rtpengine_hash.c +++ b/modules/rtpengine/rtpengine_hash.c @@ -68,8 +68,27 @@ int rtpengine_hash_table_init(int size) { } memset(rtpengine_hash_table->entry_list, 0, hash_table_size * sizeof(struct rtpengine_hash_entry)); - // init hashtable entry_list[i] (head never filled); destroy table on error + // init hashtable row_locks + rtpengine_hash_table->row_locks = shm_malloc(hash_table_size * sizeof(gen_lock_t*)); + if (!rtpengine_hash_table->row_locks) { + LM_ERR("no shm left to create rtpengine_hash_table->row_locks\n"); + rtpengine_hash_table_destroy(); + return 0; + } + memset(rtpengine_hash_table->row_locks, 0, hash_table_size * sizeof(gen_lock_t*)); + + // init hashtable row_totals + rtpengine_hash_table->row_totals = shm_malloc(hash_table_size * sizeof(unsigned int)); + if (!rtpengine_hash_table->row_totals) { + LM_ERR("no shm left to create rtpengine_hash_table->row_totals\n"); + rtpengine_hash_table_destroy(); + return 0; + } + memset(rtpengine_hash_table->row_totals, 0, hash_table_size * sizeof(unsigned int)); + + // init hashtable entry_list[i], row_locks[i] and row_totals[i] for (i = 0; i < hash_table_size; i++) { + // init hashtable row_entry_list[i] rtpengine_hash_table->entry_list[i] = shm_malloc(sizeof(struct rtpengine_hash_entry)); if (!rtpengine_hash_table->entry_list[i]) { LM_ERR("no shm left to create rtpengine_hash_table->entry_list[%d]\n", i); @@ -78,22 +97,10 @@ int rtpengine_hash_table_init(int size) { } memset(rtpengine_hash_table->entry_list[i], 0, sizeof(struct rtpengine_hash_entry)); - // never expire the head of the hashtable index lists rtpengine_hash_table->entry_list[i]->tout = -1; rtpengine_hash_table->entry_list[i]->next = NULL; - rtpengine_hash_table->total = 0; - } - - // init hashtable row_locks - rtpengine_hash_table->row_locks = shm_malloc(hash_table_size * sizeof(gen_lock_t*)); - if (!rtpengine_hash_table->row_locks) { - LM_ERR("no shm left to create rtpengine_hash_table->row_locks\n"); - rtpengine_hash_table_destroy(); - return 0; - } - // init hashtable row_locks[i] - for (i = 0; i < hash_table_size; i++) { + // init hashtable row_locks[i] rtpengine_hash_table->row_locks[i] = lock_alloc(); if (!rtpengine_hash_table->row_locks[i]) { LM_ERR("no shm left to create rtpengine_hash_table->row_locks[%d]\n", i); @@ -108,17 +115,9 @@ int rtpengine_hash_table_init(int size) { int rtpengine_hash_table_destroy() { int i; - // check rtpengine hashtable - if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table\n"); - return 0; - } - - // check rtpengine hashtable->entry_list - if (!rtpengine_hash_table->entry_list) { - LM_ERR("NULL rtpengine_hash_table->entry_list\n"); - shm_free(rtpengine_hash_table); - rtpengine_hash_table = NULL; + // sanity checks + if (!rtpengine_hash_table_sanity_checks()) { + LM_ERR("sanity checks failed\n"); return 0; } @@ -132,6 +131,7 @@ int rtpengine_hash_table_destroy() { return 0; } rtpengine_hash_table_free_entry_list(rtpengine_hash_table->entry_list[i]); + rtpengine_hash_table->entry_list[i] = NULL; lock_release(rtpengine_hash_table->row_locks[i]); // destroy hashtable row_locks[i] @@ -147,6 +147,10 @@ int rtpengine_hash_table_destroy() { shm_free(rtpengine_hash_table->row_locks); rtpengine_hash_table->row_locks = NULL; + // destroy hashtable row_totals + shm_free(rtpengine_hash_table->row_totals); + rtpengine_hash_table->row_totals = NULL; + // destroy hashtable shm_free(rtpengine_hash_table); rtpengine_hash_table = NULL; @@ -159,21 +163,9 @@ int rtpengine_hash_table_insert(str callid, str viabranch, struct rtpengine_hash struct rtpengine_hash_entry *new_entry = (struct rtpengine_hash_entry *) value; unsigned int hash_index; - // check rtpengine hashtable - if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table\n"); - return 0; - } - - // check rtpengine hashtable->entry_list - if (!rtpengine_hash_table->entry_list) { - LM_ERR("NULL rtpengine_hash_table->entry_list\n"); - return 0; - } - - // check rtpengine hashtable->row_locks - if (!rtpengine_hash_table->row_locks) { - LM_ERR("NULL rtpengine_hash_table->row_locks\n"); + // sanity checks + if (!rtpengine_hash_table_sanity_checks()) { + LM_ERR("sanity checks failed\n"); return 0; } @@ -182,6 +174,7 @@ int rtpengine_hash_table_insert(str callid, str viabranch, struct rtpengine_hash entry = rtpengine_hash_table->entry_list[hash_index]; last_entry = entry; + // lock if (rtpengine_hash_table->row_locks[hash_index]) { lock_get(rtpengine_hash_table->row_locks[hash_index]); } else { @@ -189,7 +182,6 @@ int rtpengine_hash_table_insert(str callid, str viabranch, struct rtpengine_hash return 0; } - // lock while (entry) { // if found, don't add new entry if (str_equal(entry->callid, new_entry->callid) && @@ -214,7 +206,7 @@ int rtpengine_hash_table_insert(str callid, str viabranch, struct rtpengine_hash entry = last_entry; // update total - rtpengine_hash_table->total--; + rtpengine_hash_table->row_totals[hash_index]--; } // next entry in the list @@ -225,7 +217,7 @@ int rtpengine_hash_table_insert(str callid, str viabranch, struct rtpengine_hash last_entry->next = new_entry; // update total - rtpengine_hash_table->total++; + rtpengine_hash_table->row_totals[hash_index]++; // unlock lock_release(rtpengine_hash_table->row_locks[hash_index]); @@ -237,15 +229,9 @@ int rtpengine_hash_table_remove(str callid, str viabranch) { struct rtpengine_hash_entry *entry, *last_entry; unsigned int hash_index; - // check rtpengine hashtable - if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table\n"); - return 0; - } - - // check rtpengine hashtable->entry_list - if (!rtpengine_hash_table->entry_list) { - LM_ERR("NULL rtpengine_hash_table->entry_list\n"); + // sanity checks + if (!rtpengine_hash_table_sanity_checks()) { + LM_ERR("sanity checks failed\n"); return 0; } @@ -261,6 +247,7 @@ int rtpengine_hash_table_remove(str callid, str viabranch) { LM_ERR("NULL rtpengine_hash_table->row_locks[%d]\n", hash_index); return 0; } + while (entry) { // if callid found, delete entry if (str_equal(entry->callid, callid) && @@ -270,7 +257,7 @@ int rtpengine_hash_table_remove(str callid, str viabranch) { rtpengine_hash_table_free_entry(entry); // update total - rtpengine_hash_table->total--; + rtpengine_hash_table->row_totals[hash_index]--; // unlock lock_release(rtpengine_hash_table->row_locks[hash_index]); @@ -290,7 +277,7 @@ int rtpengine_hash_table_remove(str callid, str viabranch) { entry = last_entry; // update total - rtpengine_hash_table->total--; + rtpengine_hash_table->row_totals[hash_index]--; } last_entry = entry; @@ -308,16 +295,10 @@ struct rtpp_node *rtpengine_hash_table_lookup(str callid, str viabranch) { unsigned int hash_index; struct rtpp_node *node; - // check rtpengine hashtable - if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table\n"); - return NULL; - } - - // check rtpengine hashtable->entry_list - if (!rtpengine_hash_table->entry_list) { - LM_ERR("NULL rtpengine_hash_table->entry_list\n"); - return NULL; + // sanity checks + if (!rtpengine_hash_table_sanity_checks()) { + LM_ERR("sanity checks failed\n"); + return 0; } // get first entry from entry list; jump over unused list head @@ -332,6 +313,7 @@ struct rtpp_node *rtpengine_hash_table_lookup(str callid, str viabranch) { LM_ERR("NULL rtpengine_hash_table->row_locks[%d]\n", hash_index); return 0; } + while (entry) { // if callid found, return entry if (str_equal(entry->callid, callid) && @@ -356,7 +338,7 @@ struct rtpp_node *rtpengine_hash_table_lookup(str callid, str viabranch) { entry = last_entry; // update total - rtpengine_hash_table->total--; + rtpengine_hash_table->row_totals[hash_index]--; } last_entry = entry; @@ -374,19 +356,12 @@ void rtpengine_hash_table_print() { int i; struct rtpengine_hash_entry *entry, *last_entry; - // check rtpengine hashtable - if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table\n"); - return ; - } - - // check rtpengine hashtable->entry_list - if (!rtpengine_hash_table->entry_list) { - LM_ERR("NULL rtpengine_hash_table->entry_list\n"); + // sanity checks + if (!rtpengine_hash_table_sanity_checks()) { + LM_ERR("sanity checks failed\n"); return ; } - // print hashtable for (i = 0; i < hash_table_size; i++) { // lock @@ -413,7 +388,7 @@ void rtpengine_hash_table_print() { entry = last_entry; // update total - rtpengine_hash_table->total--; + rtpengine_hash_table->row_totals[i]--; } else { LM_DBG("hash_index=%d callid=%.*s tout=%u\n", i, entry->callid.len, entry->callid.s, entry->tout - get_ticks()); @@ -430,18 +405,25 @@ void rtpengine_hash_table_print() { } unsigned int rtpengine_hash_table_total() { + int i; + unsigned int total = 0; - // check rtpengine hashtable - if (!rtpengine_hash_table) { - LM_ERR("NULL rtpengine_hash_table\n"); + // sanity checks + if (!rtpengine_hash_table_sanity_checks()) { + LM_ERR("sanity checks failed\n"); return 0; } - return rtpengine_hash_table->total; + for (i = 0; i < hash_table_size; i++) { + total += rtpengine_hash_table->row_totals[i]; + } + + return total; } void rtpengine_hash_table_free_entry(struct rtpengine_hash_entry *entry) { if (!entry) { + LM_ERR("try to free a NULL entry\n"); return ; } @@ -465,6 +447,7 @@ void rtpengine_hash_table_free_entry_list(struct rtpengine_hash_entry *entry_lis struct rtpengine_hash_entry *entry, *last_entry; if (!entry_list) { + LM_ERR("try to free a NULL entry_list\n"); return ; } @@ -481,6 +464,7 @@ void rtpengine_hash_table_free_entry_list(struct rtpengine_hash_entry *entry_lis void rtpengine_hash_table_free_row_lock(gen_lock_t *row_lock) { if (!row_lock) { + LM_ERR("try to free a NULL lock\n"); return ; } @@ -488,3 +472,31 @@ void rtpengine_hash_table_free_row_lock(gen_lock_t *row_lock) { return ; } + +int rtpengine_hash_table_sanity_checks() { + // check rtpengine hashtable + if (!rtpengine_hash_table) { + LM_ERR("NULL rtpengine_hash_table\n"); + return 0; + } + + // check rtpengine hashtable->entry_list + if (!rtpengine_hash_table->entry_list) { + LM_ERR("NULL rtpengine_hash_table->entry_list\n"); + return 0; + } + + // check rtpengine hashtable->row_locks + if (!rtpengine_hash_table->row_locks) { + LM_ERR("NULL rtpengine_hash_table->row_locks\n"); + return 0; + } + + // check rtpengine hashtable->row_totals + if (!rtpengine_hash_table->row_totals) { + LM_ERR("NULL rtpengine_hash_table->row_totals\n"); + return 0; + } + + return 1; +} diff --git a/modules/rtpengine/rtpengine_hash.h b/modules/rtpengine/rtpengine_hash.h index c4c67baa774..31036ad93d9 100644 --- a/modules/rtpengine/rtpengine_hash.h +++ b/modules/rtpengine/rtpengine_hash.h @@ -17,9 +17,9 @@ struct rtpengine_hash_entry { /* table */ struct rtpengine_hash_table { - struct rtpengine_hash_entry **entry_list; // hastable - gen_lock_t **row_locks; // hastable row locks - unsigned int total; // total number of entries in the hashtable + struct rtpengine_hash_entry **entry_list; // hashtable + gen_lock_t **row_locks; // vector of pointers to locks + unsigned int *row_totals; // vector of numbers of entries in the hashtable rows }; @@ -35,5 +35,6 @@ void rtpengine_hash_table_free_entry(struct rtpengine_hash_entry *entry); void rtpengine_hash_table_free_entry_list(struct rtpengine_hash_entry *entry_list); void rtpengine_hash_table_free_row_lock(gen_lock_t *lock); +int rtpengine_hash_table_sanity_checks(); #endif From 5ad022a4f5e959b875e9f590eca4e7e1866836bb Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Wed, 9 Dec 2015 11:41:55 +0200 Subject: [PATCH 014/142] rtpengine: Move the size inside the hash table - struct rtpengine_hash_table now contains the table size. - rename the entry_list to row_entry_list --- modules/rtpengine/rtpengine_hash.c | 69 +++++++++++++++--------------- modules/rtpengine/rtpengine_hash.h | 9 ++-- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/modules/rtpengine/rtpengine_hash.c b/modules/rtpengine/rtpengine_hash.c index 0062da888cc..821e2feea30 100644 --- a/modules/rtpengine/rtpengine_hash.c +++ b/modules/rtpengine/rtpengine_hash.c @@ -7,7 +7,6 @@ #include "../../timer.h" static struct rtpengine_hash_table *rtpengine_hash_table; -static int hash_table_size; /* from sipwise rtpengine */ static int str_cmp_str(const str a, const str b) { @@ -36,12 +35,13 @@ static unsigned int str_hash(str s) { it.len--; } - return ret % hash_table_size; + return ret % rtpengine_hash_table->size; } /* rtpengine hash API */ int rtpengine_hash_table_init(int size) { int i; + int hash_table_size; // init hash table size if (size < 1) { @@ -58,15 +58,16 @@ int rtpengine_hash_table_init(int size) { return 0; } memset(rtpengine_hash_table, 0, sizeof(struct rtpengine_hash_table)); + rtpengine_hash_table->size = hash_table_size; - // init hashtable entry_list - rtpengine_hash_table->entry_list = shm_malloc(hash_table_size * sizeof(struct rtpengine_hash_entry)); - if (!rtpengine_hash_table->entry_list) { - LM_ERR("no shm left to create rtpengine_hash_table->entry_list\n"); + // init hashtable row_entry_list + rtpengine_hash_table->row_entry_list = shm_malloc(rtpengine_hash_table->size * sizeof(struct rtpengine_hash_entry*)); + if (!rtpengine_hash_table->row_entry_list) { + LM_ERR("no shm left to create rtpengine_hash_table->row_entry_list\n"); rtpengine_hash_table_destroy(); return 0; } - memset(rtpengine_hash_table->entry_list, 0, hash_table_size * sizeof(struct rtpengine_hash_entry)); + memset(rtpengine_hash_table->row_entry_list, 0, rtpengine_hash_table->size * sizeof(struct rtpengine_hash_entry*)); // init hashtable row_locks rtpengine_hash_table->row_locks = shm_malloc(hash_table_size * sizeof(gen_lock_t*)); @@ -86,19 +87,19 @@ int rtpengine_hash_table_init(int size) { } memset(rtpengine_hash_table->row_totals, 0, hash_table_size * sizeof(unsigned int)); - // init hashtable entry_list[i], row_locks[i] and row_totals[i] + // init hashtable row_entry_list[i], row_locks[i] and row_totals[i] for (i = 0; i < hash_table_size; i++) { // init hashtable row_entry_list[i] - rtpengine_hash_table->entry_list[i] = shm_malloc(sizeof(struct rtpengine_hash_entry)); - if (!rtpengine_hash_table->entry_list[i]) { - LM_ERR("no shm left to create rtpengine_hash_table->entry_list[%d]\n", i); + rtpengine_hash_table->row_entry_list[i] = shm_malloc(sizeof(struct rtpengine_hash_entry)); + if (!rtpengine_hash_table->row_entry_list[i]) { + LM_ERR("no shm left to create rtpengine_hash_table->row_entry_list[%d]\n", i); rtpengine_hash_table_destroy(); return 0; } - memset(rtpengine_hash_table->entry_list[i], 0, sizeof(struct rtpengine_hash_entry)); + memset(rtpengine_hash_table->row_entry_list[i], 0, sizeof(struct rtpengine_hash_entry)); - rtpengine_hash_table->entry_list[i]->tout = -1; - rtpengine_hash_table->entry_list[i]->next = NULL; + rtpengine_hash_table->row_entry_list[i]->tout = -1; + rtpengine_hash_table->row_entry_list[i]->next = NULL; // init hashtable row_locks[i] rtpengine_hash_table->row_locks[i] = lock_alloc(); @@ -122,16 +123,16 @@ int rtpengine_hash_table_destroy() { } // destroy hashtable content - for (i = 0; i < hash_table_size; i++) { - // destroy hashtable entry_list[i] + for (i = 0; i < rtpengine_hash_table->size; i++) { + // destroy hashtable row_entry_list[i] if (rtpengine_hash_table->row_locks[i]) { lock_get(rtpengine_hash_table->row_locks[i]); } else { LM_ERR("NULL rtpengine_hash_table->row_locks[%d]\n", i); return 0; } - rtpengine_hash_table_free_entry_list(rtpengine_hash_table->entry_list[i]); - rtpengine_hash_table->entry_list[i] = NULL; + rtpengine_hash_table_free_row_entry_list(rtpengine_hash_table->row_entry_list[i]); + rtpengine_hash_table->row_entry_list[i] = NULL; lock_release(rtpengine_hash_table->row_locks[i]); // destroy hashtable row_locks[i] @@ -139,9 +140,9 @@ int rtpengine_hash_table_destroy() { rtpengine_hash_table->row_locks[i] = NULL; } - // destroy hashtable entry_list - shm_free(rtpengine_hash_table->entry_list); - rtpengine_hash_table->entry_list = NULL; + // destroy hashtable row_entry_list + shm_free(rtpengine_hash_table->row_entry_list); + rtpengine_hash_table->row_entry_list = NULL; // destroy hashtable row_locks shm_free(rtpengine_hash_table->row_locks); @@ -171,7 +172,7 @@ int rtpengine_hash_table_insert(str callid, str viabranch, struct rtpengine_hash // get entry list hash_index = str_hash(callid); - entry = rtpengine_hash_table->entry_list[hash_index]; + entry = rtpengine_hash_table->row_entry_list[hash_index]; last_entry = entry; // lock @@ -237,7 +238,7 @@ int rtpengine_hash_table_remove(str callid, str viabranch) { // get first entry from entry list; jump over unused list head hash_index = str_hash(callid); - entry = rtpengine_hash_table->entry_list[hash_index]; + entry = rtpengine_hash_table->row_entry_list[hash_index]; last_entry = entry; // lock @@ -303,7 +304,7 @@ struct rtpp_node *rtpengine_hash_table_lookup(str callid, str viabranch) { // get first entry from entry list; jump over unused list head hash_index = str_hash(callid); - entry = rtpengine_hash_table->entry_list[hash_index]; + entry = rtpengine_hash_table->row_entry_list[hash_index]; last_entry = entry; // lock @@ -363,7 +364,7 @@ void rtpengine_hash_table_print() { } // print hashtable - for (i = 0; i < hash_table_size; i++) { + for (i = 0; i < rtpengine_hash_table->size; i++) { // lock if (rtpengine_hash_table->row_locks[i]) { lock_get(rtpengine_hash_table->row_locks[i]); @@ -372,7 +373,7 @@ void rtpengine_hash_table_print() { return ; } - entry = rtpengine_hash_table->entry_list[i]; + entry = rtpengine_hash_table->row_entry_list[i]; last_entry = entry; while (entry) { @@ -414,7 +415,7 @@ unsigned int rtpengine_hash_table_total() { return 0; } - for (i = 0; i < hash_table_size; i++) { + for (i = 0; i < rtpengine_hash_table->size; i++) { total += rtpengine_hash_table->row_totals[i]; } @@ -443,15 +444,15 @@ void rtpengine_hash_table_free_entry(struct rtpengine_hash_entry *entry) { return ; } -void rtpengine_hash_table_free_entry_list(struct rtpengine_hash_entry *entry_list) { +void rtpengine_hash_table_free_row_entry_list(struct rtpengine_hash_entry *row_entry_list) { struct rtpengine_hash_entry *entry, *last_entry; - if (!entry_list) { - LM_ERR("try to free a NULL entry_list\n"); + if (!row_entry_list) { + LM_ERR("try to free a NULL row_entry_list\n"); return ; } - entry = entry_list; + entry = row_entry_list; while (entry) { last_entry = entry; entry = entry->next; @@ -480,9 +481,9 @@ int rtpengine_hash_table_sanity_checks() { return 0; } - // check rtpengine hashtable->entry_list - if (!rtpengine_hash_table->entry_list) { - LM_ERR("NULL rtpengine_hash_table->entry_list\n"); + // check rtpengine hashtable->row_entry_list + if (!rtpengine_hash_table->row_entry_list) { + LM_ERR("NULL rtpengine_hash_table->row_entry_list\n"); return 0; } diff --git a/modules/rtpengine/rtpengine_hash.h b/modules/rtpengine/rtpengine_hash.h index 31036ad93d9..bffb650cc74 100644 --- a/modules/rtpengine/rtpengine_hash.h +++ b/modules/rtpengine/rtpengine_hash.h @@ -17,9 +17,10 @@ struct rtpengine_hash_entry { /* table */ struct rtpengine_hash_table { - struct rtpengine_hash_entry **entry_list; // hashtable - gen_lock_t **row_locks; // vector of pointers to locks - unsigned int *row_totals; // vector of numbers of entries in the hashtable rows + struct rtpengine_hash_entry **row_entry_list; // vector of size pointers to entry + gen_lock_t **row_locks; // vector of size pointers to locks + unsigned int *row_totals; // vector of size numbers of entries in the hashtable rows + unsigned int size; // hash table size }; @@ -32,7 +33,7 @@ void rtpengine_hash_table_print(); unsigned int rtpengine_hash_table_total(); void rtpengine_hash_table_free_entry(struct rtpengine_hash_entry *entry); -void rtpengine_hash_table_free_entry_list(struct rtpengine_hash_entry *entry_list); +void rtpengine_hash_table_free_row_entry_list(struct rtpengine_hash_entry *row_entry_list); void rtpengine_hash_table_free_row_lock(gen_lock_t *lock); int rtpengine_hash_table_sanity_checks(); From 305381bb6b40dc4859f0862411a0c1a261b476c2 Mon Sep 17 00:00:00 2001 From: Dmitri Savolainen Date: Wed, 9 Dec 2015 15:44:03 +0300 Subject: [PATCH 015/142] htable: fixing htable.stats for max slot value add missed 'd' parameter to rpc->struct_add format string --- modules/htable/htable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/htable/htable.c b/modules/htable/htable.c index 7f55be1e89e..80764f3c9b8 100644 --- a/modules/htable/htable.c +++ b/modules/htable/htable.c @@ -1125,7 +1125,7 @@ static void htable_rpc_stats(rpc_t* rpc, void* c) ht_slot_unlock(ht, i); } - if(rpc->struct_add(th, "Sddd", + if(rpc->struct_add(th, "Sdddd", "name", &ht->name, /* str */ "slots", (int)ht->htsize, /* uint */ "all", (int)all, /* uint */ From 3b6d7a28ea0b053f27cb169ac31259e20ef4ece0 Mon Sep 17 00:00:00 2001 From: Hugh Waite Date: Wed, 9 Dec 2015 14:15:47 +0000 Subject: [PATCH 016/142] utils: Fix crash in http_query - Fixes incorrect fixup logic for http_query_post_hdr - Bug reported by jayesh1017 --- modules/utils/utils.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/modules/utils/utils.c b/modules/utils/utils.c index 368f5b9c95f..b407742ccd0 100644 --- a/modules/utils/utils.c +++ b/modules/utils/utils.c @@ -361,8 +361,7 @@ static int fixup_http_query_get(void** param, int param_no) static int fixup_free_http_query_get(void** param, int param_no) { if (param_no == 1) { - LM_WARN("free function has not been defined for spve\n"); - return 0; + return fixup_free_spve_null(param, 1); } if (param_no == 2) { @@ -406,7 +405,7 @@ static int fixup_http_query_post(void** param, int param_no) */ static int fixup_http_query_post_hdr(void** param, int param_no) { - if ((param_no >= 1) || (param_no <= 3)) { + if ((param_no >= 1) && (param_no <= 3)) { return fixup_spve_null(param, 1); } @@ -432,8 +431,7 @@ static int fixup_http_query_post_hdr(void** param, int param_no) static int fixup_free_http_query_post(void** param, int param_no) { if ((param_no == 1) || (param_no == 2)) { - LM_WARN("free function has not been defined for spve\n"); - return 0; + return fixup_free_spve_null(param, 1); } if (param_no == 3) { @@ -449,12 +447,11 @@ static int fixup_free_http_query_post(void** param, int param_no) */ static int fixup_free_http_query_post_hdr(void** param, int param_no) { - if ((param_no >= 1) || (param_no <= 2)) { - LM_WARN("free function has not been defined for spve\n"); - return 0; + if ((param_no >= 1) && (param_no <= 3)) { + return fixup_free_spve_null(param, 1); } - if (param_no == 3) { + if (param_no == 4) { return fixup_free_pvar_null(param, 1); } From 12160de3c2052c4696b8c073b9fa5919f6da7060 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 9 Dec 2015 23:27:09 +0100 Subject: [PATCH 017/142] core: skip zero char and whitespaces before parsing first line in parse_msg() - reported by Vasiliy Ganchev --- parser/msg_parser.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/parser/msg_parser.c b/parser/msg_parser.c index b907772d211..21b3cc2f464 100644 --- a/parser/msg_parser.c +++ b/parser/msg_parser.c @@ -589,9 +589,11 @@ int parse_msg(char* const buf, const unsigned int len, struct sip_msg* const msg int offset; hdr_flags_t flags; - /* eat crlf from the beginning */ - for (tmp=buf; (*tmp=='\n' || *tmp=='\r')&& - tmp-buf < len ; tmp++); + /* eat crlf & whitespaces from the beginning */ + for (tmp=buf; (tmp-buf < len) + && (*tmp=='\n' || *tmp=='\r' || *tmp=='\0' + || *tmp=='\t' || *tmp==' '); + tmp++); offset=tmp-buf; fl=&(msg->first_line); rest=parse_first_line(tmp, len-offset, fl); From fd79adb4975fc0799fe8488d1dd1a771041a0939 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Thu, 10 Dec 2015 09:33:32 +0100 Subject: [PATCH 018/142] dispatcher: proper handling of socket parameter when is not last in attrs - parsing socket function expects a null terminated string --- modules/dispatcher/dispatch.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/modules/dispatcher/dispatch.c b/modules/dispatcher/dispatch.c index 1188692290c..3638a9c8f8a 100644 --- a/modules/dispatcher/dispatch.c +++ b/modules/dispatcher/dispatch.c @@ -255,6 +255,7 @@ int add_dest2list(int id, str uri, int flags, int priority, str *attrs, int orig_id = 0, orig_nr = 0; str host; int port, proto; + char c = 0; ds_set_t *orig_ds_lists = ds_lists[list_idx]; /* check uri */ @@ -329,11 +330,23 @@ int add_dest2list(int id, str uri, int flags, int priority, str *attrs, /* check socket attribute */ if (dp->attrs.socket.s && dp->attrs.socket.len > 0) { + /* parse_phostport(...) expects 0-terminated string + * - after socket parameter is either ';' or '\0' */ + if(dp->attrs.socket.s[dp->attrs.socket.len]!='\0') { + c = dp->attrs.socket.s[dp->attrs.socket.len]; + dp->attrs.socket.s[dp->attrs.socket.len] = '\0'; + } if (parse_phostport(dp->attrs.socket.s, &host.s, &host.len, &port, &proto)!=0) { LM_ERR("bad socket <%.*s>\n", dp->attrs.socket.len, dp->attrs.socket.s); + if(c!=0) { + dp->attrs.socket.s[dp->attrs.socket.len] = c; + } goto err; } + if(c!=0) { + dp->attrs.socket.s[dp->attrs.socket.len] = c; + } dp->sock = grep_sock_info( &host, (unsigned short)port, proto); if (dp->sock==0) { LM_ERR("non-local socket <%.*s>\n", dp->attrs.socket.len, dp->attrs.socket.s); From 95cd1062a937568322665bacd019d21fc20d57c0 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Thu, 10 Dec 2015 11:38:10 +0200 Subject: [PATCH 019/142] rtpengine: _destroy() sanity + memory free _destroy() sanity checking, with memory free, when possible: - alloc the locks first. - free the locks last. - consider content already hadled for a NULL lock (or NULL lock vector). - make _free_row_lock() static. --- modules/rtpengine/rtpengine_hash.c | 129 +++++++++++++++++++---------- modules/rtpengine/rtpengine_hash.h | 1 - 2 files changed, 85 insertions(+), 45 deletions(-) diff --git a/modules/rtpengine/rtpengine_hash.c b/modules/rtpengine/rtpengine_hash.c index 821e2feea30..f8e610d82d9 100644 --- a/modules/rtpengine/rtpengine_hash.c +++ b/modules/rtpengine/rtpengine_hash.c @@ -6,6 +6,9 @@ #include "../../locking.h" #include "../../timer.h" +static void rtpengine_hash_table_free_row_lock(gen_lock_t *row_lock); + + static struct rtpengine_hash_table *rtpengine_hash_table; /* from sipwise rtpengine */ @@ -60,15 +63,6 @@ int rtpengine_hash_table_init(int size) { memset(rtpengine_hash_table, 0, sizeof(struct rtpengine_hash_table)); rtpengine_hash_table->size = hash_table_size; - // init hashtable row_entry_list - rtpengine_hash_table->row_entry_list = shm_malloc(rtpengine_hash_table->size * sizeof(struct rtpengine_hash_entry*)); - if (!rtpengine_hash_table->row_entry_list) { - LM_ERR("no shm left to create rtpengine_hash_table->row_entry_list\n"); - rtpengine_hash_table_destroy(); - return 0; - } - memset(rtpengine_hash_table->row_entry_list, 0, rtpengine_hash_table->size * sizeof(struct rtpengine_hash_entry*)); - // init hashtable row_locks rtpengine_hash_table->row_locks = shm_malloc(hash_table_size * sizeof(gen_lock_t*)); if (!rtpengine_hash_table->row_locks) { @@ -78,6 +72,15 @@ int rtpengine_hash_table_init(int size) { } memset(rtpengine_hash_table->row_locks, 0, hash_table_size * sizeof(gen_lock_t*)); + // init hashtable row_entry_list + rtpengine_hash_table->row_entry_list = shm_malloc(rtpengine_hash_table->size * sizeof(struct rtpengine_hash_entry*)); + if (!rtpengine_hash_table->row_entry_list) { + LM_ERR("no shm left to create rtpengine_hash_table->row_entry_list\n"); + rtpengine_hash_table_destroy(); + return 0; + } + memset(rtpengine_hash_table->row_entry_list, 0, rtpengine_hash_table->size * sizeof(struct rtpengine_hash_entry*)); + // init hashtable row_totals rtpengine_hash_table->row_totals = shm_malloc(hash_table_size * sizeof(unsigned int)); if (!rtpengine_hash_table->row_totals) { @@ -87,8 +90,16 @@ int rtpengine_hash_table_init(int size) { } memset(rtpengine_hash_table->row_totals, 0, hash_table_size * sizeof(unsigned int)); - // init hashtable row_entry_list[i], row_locks[i] and row_totals[i] + // init hashtable row_locks[i], row_entry_list[i] and row_totals[i] for (i = 0; i < hash_table_size; i++) { + // init hashtable row_locks[i] + rtpengine_hash_table->row_locks[i] = lock_alloc(); + if (!rtpengine_hash_table->row_locks[i]) { + LM_ERR("no shm left to create rtpengine_hash_table->row_locks[%d]\n", i); + rtpengine_hash_table_destroy(); + return 0; + } + // init hashtable row_entry_list[i] rtpengine_hash_table->row_entry_list[i] = shm_malloc(sizeof(struct rtpengine_hash_entry)); if (!rtpengine_hash_table->row_entry_list[i]) { @@ -101,13 +112,8 @@ int rtpengine_hash_table_init(int size) { rtpengine_hash_table->row_entry_list[i]->tout = -1; rtpengine_hash_table->row_entry_list[i]->next = NULL; - // init hashtable row_locks[i] - rtpengine_hash_table->row_locks[i] = lock_alloc(); - if (!rtpengine_hash_table->row_locks[i]) { - LM_ERR("no shm left to create rtpengine_hash_table->row_locks[%d]\n", i); - rtpengine_hash_table_destroy(); - return 0; - } + // init hashtable row_totals[i] + rtpengine_hash_table->row_totals[i] = 0; } return 1; @@ -116,23 +122,40 @@ int rtpengine_hash_table_init(int size) { int rtpengine_hash_table_destroy() { int i; - // sanity checks - if (!rtpengine_hash_table_sanity_checks()) { - LM_ERR("sanity checks failed\n"); - return 0; + // check rtpengine hashtable + if (!rtpengine_hash_table) { + LM_ERR("NULL rtpengine_hash_table\n"); + return 1; + } + + // check rtpengine hashtable->row_locks + if (!rtpengine_hash_table->row_locks) { + LM_ERR("NULL rtpengine_hash_table->row_locks\n"); + shm_free(rtpengine_hash_table); + rtpengine_hash_table = NULL; + return 1; } // destroy hashtable content for (i = 0; i < rtpengine_hash_table->size; i++) { - // destroy hashtable row_entry_list[i] - if (rtpengine_hash_table->row_locks[i]) { + // lock + if (!rtpengine_hash_table->row_locks[i]) { + LM_ERR("NULL rtpengine_hash_table->row_locks[%d]\n", i); + continue; + } else { lock_get(rtpengine_hash_table->row_locks[i]); + } + + // check rtpengine hashtable->row_entry_list + if (!rtpengine_hash_table->row_entry_list) { + LM_ERR("NULL rtpengine_hash_table->row_entry_list\n"); } else { - LM_ERR("NULL rtpengine_hash_table->row_locks[%d]\n", i); - return 0; + // destroy hashtable row_entry_list[i] + rtpengine_hash_table_free_row_entry_list(rtpengine_hash_table->row_entry_list[i]); + rtpengine_hash_table->row_entry_list[i] = NULL; } - rtpengine_hash_table_free_row_entry_list(rtpengine_hash_table->row_entry_list[i]); - rtpengine_hash_table->row_entry_list[i] = NULL; + + // unlock lock_release(rtpengine_hash_table->row_locks[i]); // destroy hashtable row_locks[i] @@ -141,20 +164,38 @@ int rtpengine_hash_table_destroy() { } // destroy hashtable row_entry_list - shm_free(rtpengine_hash_table->row_entry_list); - rtpengine_hash_table->row_entry_list = NULL; - - // destroy hashtable row_locks - shm_free(rtpengine_hash_table->row_locks); - rtpengine_hash_table->row_locks = NULL; + if (!rtpengine_hash_table->row_entry_list) { + LM_ERR("NULL rtpengine_hash_table->row_entry_list\n"); + } else { + shm_free(rtpengine_hash_table->row_entry_list); + rtpengine_hash_table->row_entry_list = NULL; + } // destroy hashtable row_totals - shm_free(rtpengine_hash_table->row_totals); - rtpengine_hash_table->row_totals = NULL; + if (!rtpengine_hash_table->row_totals) { + LM_ERR("NULL rtpengine_hash_table->row_totals\n"); + } else { + shm_free(rtpengine_hash_table->row_totals); + rtpengine_hash_table->row_totals = NULL; + } + + // destroy hashtable row_locks + if (!rtpengine_hash_table->row_locks) { + // should not be the case; just for code symmetry + LM_ERR("NULL rtpengine_hash_table->row_locks\n"); + } else { + shm_free(rtpengine_hash_table->row_locks); + rtpengine_hash_table->row_locks = NULL; + } // destroy hashtable - shm_free(rtpengine_hash_table); - rtpengine_hash_table = NULL; + if (!rtpengine_hash_table) { + // should not be the case; just for code symmetry + LM_ERR("NULL rtpengine_hash_table\n"); + } else { + shm_free(rtpengine_hash_table); + rtpengine_hash_table = NULL; + } return 1; } @@ -463,7 +504,7 @@ void rtpengine_hash_table_free_row_entry_list(struct rtpengine_hash_entry *row_e return ; } -void rtpengine_hash_table_free_row_lock(gen_lock_t *row_lock) { +static void rtpengine_hash_table_free_row_lock(gen_lock_t *row_lock) { if (!row_lock) { LM_ERR("try to free a NULL lock\n"); return ; @@ -481,18 +522,18 @@ int rtpengine_hash_table_sanity_checks() { return 0; } - // check rtpengine hashtable->row_entry_list - if (!rtpengine_hash_table->row_entry_list) { - LM_ERR("NULL rtpengine_hash_table->row_entry_list\n"); - return 0; - } - // check rtpengine hashtable->row_locks if (!rtpengine_hash_table->row_locks) { LM_ERR("NULL rtpengine_hash_table->row_locks\n"); return 0; } + // check rtpengine hashtable->row_entry_list + if (!rtpengine_hash_table->row_entry_list) { + LM_ERR("NULL rtpengine_hash_table->row_entry_list\n"); + return 0; + } + // check rtpengine hashtable->row_totals if (!rtpengine_hash_table->row_totals) { LM_ERR("NULL rtpengine_hash_table->row_totals\n"); diff --git a/modules/rtpengine/rtpengine_hash.h b/modules/rtpengine/rtpengine_hash.h index bffb650cc74..dab6c714e81 100644 --- a/modules/rtpengine/rtpengine_hash.h +++ b/modules/rtpengine/rtpengine_hash.h @@ -35,7 +35,6 @@ unsigned int rtpengine_hash_table_total(); void rtpengine_hash_table_free_entry(struct rtpengine_hash_entry *entry); void rtpengine_hash_table_free_row_entry_list(struct rtpengine_hash_entry *row_entry_list); -void rtpengine_hash_table_free_row_lock(gen_lock_t *lock); int rtpengine_hash_table_sanity_checks(); #endif From 432c1e3b0f7ff6a9fa11e6d8ed8b897dc3f9246f Mon Sep 17 00:00:00 2001 From: Andrey Utkin Date: Sat, 12 Dec 2015 22:37:15 +0200 Subject: [PATCH 020/142] modules/websocket: ensure linkage to libcrypto Fixes linkage for Ubuntu Wily (15.10). The issue manifests itself as "undefined symbol: SHA1" error at module loading. --- modules/websocket/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/websocket/Makefile b/modules/websocket/Makefile index 915c81a7946..010aa90c973 100644 --- a/modules/websocket/Makefile +++ b/modules/websocket/Makefile @@ -13,6 +13,12 @@ SSL_BUILDER=$(shell \ if pkg-config --exists libssl; then \ echo 'pkg-config libssl'; \ fi) +ifneq($(SSL_BUILDER),) +SSL_BUILDER+=$(shell \ + if pkg-config --exists libcrypto; then \ + echo 'libcrypto'; \ + fi) +endif endif ifneq ($(SSL_BUILDER),) From aeb3e18527b565f22bd05f6c6989b2ae86968b71 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Fri, 27 Nov 2015 18:18:14 +0200 Subject: [PATCH 021/142] tmx: refactor counters Focus on: - received_replies - received_replies_absorbed (in cfX cases) - relayed_locally - relayed_received - relayed_total --- modules/tm/t_reply.c | 15 +++++++++------ modules/tm/t_stats.c | 9 ++++++--- modules/tm/t_stats.h | 17 +++++++++++------ modules/tmx/tmx_mod.c | 38 +++++++++++++++++++++++++------------- 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/modules/tm/t_reply.c b/modules/tm/t_reply.c index f4e4dcdbf04..3b8e16b348c 100644 --- a/modules/tm/t_reply.c +++ b/modules/tm/t_reply.c @@ -554,8 +554,8 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len, /* t_update_timers_after_sending_reply( rb ); */ update_reply_stats( code ); trans->relayed_reply_branch=-2; - t_stats_replied_locally(); - t_stats_replied_total(); + t_stats_relayed_locally(); + t_stats_relayed_total(); if (lock) UNLOCK_REPLIES( trans ); /* do UAC cleanup procedures in case we generated @@ -1867,7 +1867,7 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, } } update_reply_stats( relayed_code ); - t_stats_replied_total(); + t_stats_relayed_total(); if (!buf) { LOG(L_ERR, "ERROR: relay_reply: " "no mem for outbound reply buffer\n"); @@ -1890,7 +1890,7 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, memcpy( uas_rb->buffer, buf, res_len ); if (relayed_msg==FAKED_REPLY) { /* to-tags for local replies */ update_local_tags(t, &bm, uas_rb->buffer, buf); - t_stats_replied_locally(); + t_stats_relayed_locally(); } /* update the status ... */ @@ -2041,7 +2041,7 @@ enum rps local_reply( struct cell *t, struct sip_msg *p_msg, int branch, winning_msg= branch==local_winner ? p_msg : t->uac[local_winner].reply; if (winning_msg==FAKED_REPLY) { - t_stats_replied_locally(); + t_stats_relayed_locally(); winning_code = branch==local_winner ? msg_status : t->uac[local_winner].last_received; } else { @@ -2049,7 +2049,7 @@ enum rps local_reply( struct cell *t, struct sip_msg *p_msg, int branch, } t->uas.status = winning_code; update_reply_stats( winning_code ); - t_stats_replied_total(); + t_stats_relayed_total(); if (unlikely(is_invite(t) && winning_msg!=FAKED_REPLY && winning_code>=200 && winning_code <300 && has_tran_tmcbs(t, TMCB_LOCAL_COMPLETED) )) { @@ -2143,6 +2143,9 @@ int reply_received( struct sip_msg *p_msg ) if ( (t==0)||(t==T_UNDEFINED)) goto trans_not_found; + /* if transaction found, increment the received_replies counter */ + t_stats_received_replies(); + if (unlikely(branch==T_BR_UNDEFINED)) BUG("invalid branch, please report to sr-dev@sip-router.org\n"); tm_ctx_set_branch_index(branch); diff --git a/modules/tm/t_stats.c b/modules/tm/t_stats.c index 8187568a3f0..28fe04e0997 100644 --- a/modules/tm/t_stats.c +++ b/modules/tm/t_stats.c @@ -93,8 +93,9 @@ void free_tm_stats() (res)->completed_5xx=(s1)->completed_5xx+(s2)->completed_5xx; \ (res)->completed_6xx=(s1)->completed_6xx+(s2)->completed_6xx; \ (res)->completed_2xx=(s1)->completed_2xx+(s2)->completed_2xx; \ - (res)->replied_locally=(s1)->replied_locally+(s2)->replied_locally; \ - (res)->replied_total=(s1)->replied_total+(s2)->replied_total; \ + (res)->received_replies=(s1)->received_replies+(s2)->received_replies; \ + (res)->relayed_locally=(s1)->relayed_locally+(s2)->relayed_locally; \ + (res)->relayed_total=(s1)->relayed_total+(s2)->relayed_total; \ (res)->deleted=(s1)->deleted+(s2)->deleted; \ }while(0) @@ -137,7 +138,9 @@ void tm_rpc_stats(rpc_t* rpc, void* c) (unsigned) waiting); rpc->struct_add(st, "d", "total", (unsigned) all.transactions); rpc->struct_add(st, "d", "total_local", (unsigned)all.client_transactions); - rpc->struct_add(st, "d", "replied_locally", (unsigned)all.replied_locally); + rpc->struct_add(st, "d", "received_replies", (unsigned)all.received_replies); + rpc->struct_add(st, "d", "relayed_locally", (unsigned)all.relayed_locally); + rpc->struct_add(st, "d", "relayed_total", (unsigned)all.relayed_total); rpc->struct_add(st, "ddddd", "6xx", (unsigned int)all.completed_6xx, "5xx", (unsigned int)all.completed_5xx, diff --git a/modules/tm/t_stats.h b/modules/tm/t_stats.h index dcb0be7660f..5be3c701d9c 100644 --- a/modules/tm/t_stats.h +++ b/modules/tm/t_stats.h @@ -43,8 +43,9 @@ struct t_proc_stats { /* number of transactions which completed with this status */ stat_counter completed_3xx, completed_4xx, completed_5xx, completed_6xx, completed_2xx; - stat_counter replied_locally; - stat_counter replied_total; + stat_counter received_replies; + stat_counter relayed_locally; + stat_counter relayed_total; stat_counter deleted; #ifdef TM_MORE_STATS /* number of created transactions */ @@ -121,15 +122,19 @@ inline static void update_reply_stats( int code ) { } } +inline void static t_stats_received_replies(void) +{ + tm_stats[process_no].s.received_replies++; +} -inline void static t_stats_replied_locally(void) +inline void static t_stats_relayed_locally(void) { - tm_stats[process_no].s.replied_locally++; + tm_stats[process_no].s.relayed_locally++; } -inline void static t_stats_replied_total(void) +inline void static t_stats_relayed_total(void) { - tm_stats[process_no].s.replied_total++; + tm_stats[process_no].s.relayed_total++; } diff --git a/modules/tmx/tmx_mod.c b/modules/tmx/tmx_mod.c index 10e509d0520..38a73ff2d0b 100644 --- a/modules/tmx/tmx_mod.c +++ b/modules/tmx/tmx_mod.c @@ -108,8 +108,10 @@ unsigned long tmx_stats_trans_6xx(void); unsigned long tmx_stats_trans_inuse(void); unsigned long tmx_stats_trans_active(void); unsigned long tmx_stats_rcv_rpls(void); -unsigned long tmx_stats_rld_rpls(void); -unsigned long tmx_stats_loc_rpls(void); +unsigned long tmx_stats_abs_rpls(void); +unsigned long tmx_stats_rld_rcv_rpls(void); +unsigned long tmx_stats_rld_loc_rpls(void); +unsigned long tmx_stats_rld_tot_rpls(void); static stat_export_t mod_stats[] = { {"UAS_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_uas_trans }, @@ -122,8 +124,10 @@ static stat_export_t mod_stats[] = { {"inuse_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_inuse }, {"active_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_active}, {"received_replies" , STAT_IS_FUNC, (stat_var**)tmx_stats_rcv_rpls }, - {"relayed_replies" , STAT_IS_FUNC, (stat_var**)tmx_stats_rld_rpls }, - {"local_replies" , STAT_IS_FUNC, (stat_var**)tmx_stats_loc_rpls }, + {"received_replies_absorbed", STAT_IS_FUNC, (stat_var**)tmx_stats_abs_rpls }, + {"relayed_locally" , STAT_IS_FUNC, (stat_var**)tmx_stats_rld_loc_rpls}, + {"relayed_received" , STAT_IS_FUNC, (stat_var**)tmx_stats_rld_rcv_rpls}, + {"relayed_total" , STAT_IS_FUNC, (stat_var**)tmx_stats_rld_tot_rpls}, {0,0,0} }; #endif @@ -810,23 +814,31 @@ unsigned long tmx_stats_trans_active(void) unsigned long tmx_stats_rcv_rpls(void) { tmx_stats_update(); - return _tmx_stats_all.completed_6xx - + _tmx_stats_all.completed_5xx - + _tmx_stats_all.completed_4xx - + _tmx_stats_all.completed_3xx - + _tmx_stats_all.completed_2xx; + return _tmx_stats_all.received_replies; } -unsigned long tmx_stats_rld_rpls(void) +unsigned long tmx_stats_abs_rpls(void) { tmx_stats_update(); - return _tmx_stats_all.replied_total - _tmx_stats_all.replied_locally; + return _tmx_stats_all.received_replies - tmx_stats_rld_rcv_rpls(); } -unsigned long tmx_stats_loc_rpls(void) +unsigned long tmx_stats_rld_loc_rpls(void) { tmx_stats_update(); - return _tmx_stats_all.replied_locally; + return _tmx_stats_all.relayed_locally; +} + +unsigned long tmx_stats_rld_tot_rpls(void) +{ + tmx_stats_update(); + return _tmx_stats_all.relayed_total; +} + +unsigned long tmx_stats_rld_rcv_rpls(void) +{ + tmx_stats_update(); + return _tmx_stats_all.relayed_total - _tmx_stats_all.relayed_locally; } #endif From 572fa1b4497571ec68453c97b3080740364d3335 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Mon, 14 Dec 2015 15:02:53 +0200 Subject: [PATCH 022/142] tmx: Update doku Update doku related to the counters changes. --- modules/tmx/doc/tmx_admin.xml | 69 ++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/modules/tmx/doc/tmx_admin.xml b/modules/tmx/doc/tmx_admin.xml index 65de5972ba2..705113f4fb1 100644 --- a/modules/tmx/doc/tmx_admin.xml +++ b/modules/tmx/doc/tmx_admin.xml @@ -626,72 +626,105 @@ event_route [tm:branch-failure:contact] { Exported statistics are listed in the next sections. All statistics except inuse_transactions can be reset. -
- received_replies - - Total number of total replies received by TM module. - -
-
- relayed_replies - - Total number of replies received and relayed by TM module. - -
-
- local_replies - - Total number of replies local generated by TM module. - -
+
UAS_transactions Total number of transactions created by received requests.
+
UAC_transactions Total number of transactions created by local generated requests.
+
2xx_transactions Total number of transactions completed with 2xx replies.
+
3xx_transactions Total number of transactions completed with 3xx replies.
+
4xx_transactions Total number of transactions completed with 4xx replies.
+
5xx_transactions Total number of transactions completed with 5xx replies.
+
6xx_transactions Total number of transactions completed with 6xx replies.
+
inuse_transactions Number of transactions existing in memory at current time.
+ +
+ active_transactions + + Number of ongoing transactions at current time. + +
+ +
+ received_replies + + Total number of replies received by TM module. + +
+ +
+ received_replies_absorbed + + Total number of replies received and not relayed by TM module. + +
+ +
+ tmx:relayed_locally + + Total number of replies locally generated and relayed by TM module. + +
+ +
+ relayed_received + + Total number of replies received and relayed by TM module. + +
+ +
+ relayed_total + + Total number of replies relayed by TM module. + +
+ From 4d89a50544324fdac0f08497dc142c171bfcd97d Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 14 Dec 2015 15:15:52 +0100 Subject: [PATCH 023/142] tm: avoiding conditional directives that split up parts of statements - patch by Romero Malaquias, FS#434 --- modules/tm/t_fwd.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/tm/t_fwd.c b/modules/tm/t_fwd.c index 9cd002f891a..15f0969af1c 100644 --- a/modules/tm/t_fwd.c +++ b/modules/tm/t_fwd.c @@ -146,6 +146,7 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req, str ua_bak; int free_ua; int backup_route_type; + int test_dst; snd_flags_t fwd_snd_flags_bak; snd_flags_t rpl_snd_flags_bak; struct socket_info *force_send_socket_bak; @@ -427,14 +428,14 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req, if (likely(next_hop!=0 || (flags & UAC_DNS_FAILOVER_F))){ /* next_hop present => use it for dns resolution */ #ifdef USE_DNS_FAILOVER - if (uri2dst2(&t->uac[branch].dns_h, dst, fsocket, snd_flags, - next_hop?next_hop:uri, fproto) == 0) + test_dst = (uri2dst2(&t->uac[branch].dns_h, dst, fsocket, snd_flags, + next_hop?next_hop:uri, fproto) == 0); #else /* dst filled from the uri & request (send_socket) */ - if (uri2dst2(dst, fsocket, snd_flags, - next_hop?next_hop:uri, fproto)==0) + test_dst = (uri2dst2(dst, fsocket, snd_flags, + next_hop?next_hop:uri, fproto)==0); #endif - { + if (test_dst){ ret=E_BAD_ADDRESS; goto error01; } From 6e9f017dd3509296b83f12d3467309c583a248b1 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Mon, 14 Dec 2015 17:32:02 +0200 Subject: [PATCH 024/142] tmx: Consistent naming of counters Simplify the names of the tmx counters to "rpl_*". --- modules/tm/t_reply.c | 16 +++++++------- modules/tm/t_stats.c | 12 +++++------ modules/tm/t_stats.h | 18 ++++++++-------- modules/tmx/doc/tmx_admin.xml | 14 ++++++------ modules/tmx/tmx_mod.c | 40 +++++++++++++++++------------------ 5 files changed, 50 insertions(+), 50 deletions(-) diff --git a/modules/tm/t_reply.c b/modules/tm/t_reply.c index 3b8e16b348c..9011c87e5dd 100644 --- a/modules/tm/t_reply.c +++ b/modules/tm/t_reply.c @@ -554,8 +554,8 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len, /* t_update_timers_after_sending_reply( rb ); */ update_reply_stats( code ); trans->relayed_reply_branch=-2; - t_stats_relayed_locally(); - t_stats_relayed_total(); + t_stats_rpl_generated(); + t_stats_rpl_sent(); if (lock) UNLOCK_REPLIES( trans ); /* do UAC cleanup procedures in case we generated @@ -1867,7 +1867,7 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, } } update_reply_stats( relayed_code ); - t_stats_relayed_total(); + t_stats_rpl_sent(); if (!buf) { LOG(L_ERR, "ERROR: relay_reply: " "no mem for outbound reply buffer\n"); @@ -1890,7 +1890,7 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, memcpy( uas_rb->buffer, buf, res_len ); if (relayed_msg==FAKED_REPLY) { /* to-tags for local replies */ update_local_tags(t, &bm, uas_rb->buffer, buf); - t_stats_relayed_locally(); + t_stats_rpl_generated(); } /* update the status ... */ @@ -2041,7 +2041,7 @@ enum rps local_reply( struct cell *t, struct sip_msg *p_msg, int branch, winning_msg= branch==local_winner ? p_msg : t->uac[local_winner].reply; if (winning_msg==FAKED_REPLY) { - t_stats_relayed_locally(); + t_stats_rpl_generated(); winning_code = branch==local_winner ? msg_status : t->uac[local_winner].last_received; } else { @@ -2049,7 +2049,7 @@ enum rps local_reply( struct cell *t, struct sip_msg *p_msg, int branch, } t->uas.status = winning_code; update_reply_stats( winning_code ); - t_stats_relayed_total(); + t_stats_rpl_sent(); if (unlikely(is_invite(t) && winning_msg!=FAKED_REPLY && winning_code>=200 && winning_code <300 && has_tran_tmcbs(t, TMCB_LOCAL_COMPLETED) )) { @@ -2143,8 +2143,8 @@ int reply_received( struct sip_msg *p_msg ) if ( (t==0)||(t==T_UNDEFINED)) goto trans_not_found; - /* if transaction found, increment the received_replies counter */ - t_stats_received_replies(); + /* if transaction found, increment the rpl_received counter */ + t_stats_rpl_received(); if (unlikely(branch==T_BR_UNDEFINED)) BUG("invalid branch, please report to sr-dev@sip-router.org\n"); diff --git a/modules/tm/t_stats.c b/modules/tm/t_stats.c index 28fe04e0997..e4778d08dc2 100644 --- a/modules/tm/t_stats.c +++ b/modules/tm/t_stats.c @@ -93,9 +93,9 @@ void free_tm_stats() (res)->completed_5xx=(s1)->completed_5xx+(s2)->completed_5xx; \ (res)->completed_6xx=(s1)->completed_6xx+(s2)->completed_6xx; \ (res)->completed_2xx=(s1)->completed_2xx+(s2)->completed_2xx; \ - (res)->received_replies=(s1)->received_replies+(s2)->received_replies; \ - (res)->relayed_locally=(s1)->relayed_locally+(s2)->relayed_locally; \ - (res)->relayed_total=(s1)->relayed_total+(s2)->relayed_total; \ + (res)->rpl_received=(s1)->rpl_received+(s2)->rpl_received; \ + (res)->rpl_generated=(s1)->rpl_generated+(s2)->rpl_generated; \ + (res)->rpl_sent=(s1)->rpl_sent+(s2)->rpl_sent; \ (res)->deleted=(s1)->deleted+(s2)->deleted; \ }while(0) @@ -138,9 +138,9 @@ void tm_rpc_stats(rpc_t* rpc, void* c) (unsigned) waiting); rpc->struct_add(st, "d", "total", (unsigned) all.transactions); rpc->struct_add(st, "d", "total_local", (unsigned)all.client_transactions); - rpc->struct_add(st, "d", "received_replies", (unsigned)all.received_replies); - rpc->struct_add(st, "d", "relayed_locally", (unsigned)all.relayed_locally); - rpc->struct_add(st, "d", "relayed_total", (unsigned)all.relayed_total); + rpc->struct_add(st, "d", "rpl_received", (unsigned)all.rpl_received); + rpc->struct_add(st, "d", "rpl_generated", (unsigned)all.rpl_generated); + rpc->struct_add(st, "d", "rpl_sent", (unsigned)all.rpl_sent); rpc->struct_add(st, "ddddd", "6xx", (unsigned int)all.completed_6xx, "5xx", (unsigned int)all.completed_5xx, diff --git a/modules/tm/t_stats.h b/modules/tm/t_stats.h index 5be3c701d9c..108336ef2cf 100644 --- a/modules/tm/t_stats.h +++ b/modules/tm/t_stats.h @@ -43,9 +43,9 @@ struct t_proc_stats { /* number of transactions which completed with this status */ stat_counter completed_3xx, completed_4xx, completed_5xx, completed_6xx, completed_2xx; - stat_counter received_replies; - stat_counter relayed_locally; - stat_counter relayed_total; + stat_counter rpl_received; + stat_counter rpl_generated; + stat_counter rpl_sent; stat_counter deleted; #ifdef TM_MORE_STATS /* number of created transactions */ @@ -122,19 +122,19 @@ inline static void update_reply_stats( int code ) { } } -inline void static t_stats_received_replies(void) +inline void static t_stats_rpl_received(void) { - tm_stats[process_no].s.received_replies++; + tm_stats[process_no].s.rpl_received++; } -inline void static t_stats_relayed_locally(void) +inline void static t_stats_rpl_generated(void) { - tm_stats[process_no].s.relayed_locally++; + tm_stats[process_no].s.rpl_generated++; } -inline void static t_stats_relayed_total(void) +inline void static t_stats_rpl_sent(void) { - tm_stats[process_no].s.relayed_total++; + tm_stats[process_no].s.rpl_sent++; } diff --git a/modules/tmx/doc/tmx_admin.xml b/modules/tmx/doc/tmx_admin.xml index 705113f4fb1..8c2dcfe1ba0 100644 --- a/modules/tmx/doc/tmx_admin.xml +++ b/modules/tmx/doc/tmx_admin.xml @@ -691,35 +691,35 @@ event_route [tm:branch-failure:contact] {
- received_replies + rpl_received Total number of replies received by TM module.
- received_replies_absorbed + rpl_absorbed Total number of replies received and not relayed by TM module.
- tmx:relayed_locally + rpl_relayed - Total number of replies locally generated and relayed by TM module. + Total number of replies received and relayed by TM module.
- relayed_received + rpl_generated - Total number of replies received and relayed by TM module. + Total number of replies locally generated and relayed by TM module.
- relayed_total + rpl_sent Total number of replies relayed by TM module. diff --git a/modules/tmx/tmx_mod.c b/modules/tmx/tmx_mod.c index 38a73ff2d0b..b6a9cce7b59 100644 --- a/modules/tmx/tmx_mod.c +++ b/modules/tmx/tmx_mod.c @@ -114,21 +114,21 @@ unsigned long tmx_stats_rld_loc_rpls(void); unsigned long tmx_stats_rld_tot_rpls(void); static stat_export_t mod_stats[] = { - {"UAS_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_uas_trans }, - {"UAC_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_uac_trans }, - {"2xx_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_2xx }, - {"3xx_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_3xx }, - {"4xx_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_4xx }, - {"5xx_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_5xx }, - {"6xx_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_6xx }, - {"inuse_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_inuse }, - {"active_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_active}, - {"received_replies" , STAT_IS_FUNC, (stat_var**)tmx_stats_rcv_rpls }, - {"received_replies_absorbed", STAT_IS_FUNC, (stat_var**)tmx_stats_abs_rpls }, - {"relayed_locally" , STAT_IS_FUNC, (stat_var**)tmx_stats_rld_loc_rpls}, - {"relayed_received" , STAT_IS_FUNC, (stat_var**)tmx_stats_rld_rcv_rpls}, - {"relayed_total" , STAT_IS_FUNC, (stat_var**)tmx_stats_rld_tot_rpls}, - {0,0,0} + {"UAS_transactions", STAT_IS_FUNC, (stat_var**)tmx_stats_uas_trans }, + {"UAC_transactions", STAT_IS_FUNC, (stat_var**)tmx_stats_uac_trans }, + {"2xx_transactions", STAT_IS_FUNC, (stat_var**)tmx_stats_trans_2xx }, + {"3xx_transactions", STAT_IS_FUNC, (stat_var**)tmx_stats_trans_3xx }, + {"4xx_transactions", STAT_IS_FUNC, (stat_var**)tmx_stats_trans_4xx }, + {"5xx_transactions", STAT_IS_FUNC, (stat_var**)tmx_stats_trans_5xx }, + {"6xx_transactions", STAT_IS_FUNC, (stat_var**)tmx_stats_trans_6xx }, + {"inuse_transactions", STAT_IS_FUNC, (stat_var**)tmx_stats_trans_inuse }, + {"active_transactions", STAT_IS_FUNC, (stat_var**)tmx_stats_trans_active}, + {"rpl_received", STAT_IS_FUNC, (stat_var**)tmx_stats_rcv_rpls }, + {"rpl_absorbed", STAT_IS_FUNC, (stat_var**)tmx_stats_abs_rpls }, + {"rpl_generated", STAT_IS_FUNC, (stat_var**)tmx_stats_rld_loc_rpls}, + {"rpl_relayed", STAT_IS_FUNC, (stat_var**)tmx_stats_rld_rcv_rpls}, + {"rpl_sent", STAT_IS_FUNC, (stat_var**)tmx_stats_rld_tot_rpls}, + {0, 0, 0} }; #endif @@ -814,31 +814,31 @@ unsigned long tmx_stats_trans_active(void) unsigned long tmx_stats_rcv_rpls(void) { tmx_stats_update(); - return _tmx_stats_all.received_replies; + return _tmx_stats_all.rpl_received; } unsigned long tmx_stats_abs_rpls(void) { tmx_stats_update(); - return _tmx_stats_all.received_replies - tmx_stats_rld_rcv_rpls(); + return _tmx_stats_all.rpl_received - tmx_stats_rld_rcv_rpls(); } unsigned long tmx_stats_rld_loc_rpls(void) { tmx_stats_update(); - return _tmx_stats_all.relayed_locally; + return _tmx_stats_all.rpl_generated; } unsigned long tmx_stats_rld_tot_rpls(void) { tmx_stats_update(); - return _tmx_stats_all.relayed_total; + return _tmx_stats_all.rpl_sent; } unsigned long tmx_stats_rld_rcv_rpls(void) { tmx_stats_update(); - return _tmx_stats_all.relayed_total - _tmx_stats_all.relayed_locally; + return _tmx_stats_all.rpl_sent - _tmx_stats_all.rpl_generated; } #endif From d24863d071417effe5df863736ef037ec8e0b414 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 14 Dec 2015 16:40:03 +0100 Subject: [PATCH 025/142] presence: init variable to prevent invalid cleanup on error getting presence document - reported by GH#441 --- modules/presence/publish.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/presence/publish.c b/modules/presence/publish.c index 5a48f771172..73a64c6db22 100644 --- a/modules/presence/publish.c +++ b/modules/presence/publish.c @@ -509,7 +509,7 @@ int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2) int update_hard_presentity(str *pres_uri, pres_ev_t *event, str *file_uri, str *filename) { int ret = -1, new_t, pidf_result; - str *pidf_doc; + str *pidf_doc = 0; char *sphere = NULL; presentity_t *pres = NULL; struct sip_uri parsed_uri; From a3c212f2489e4ba01c7592f68cd35fdb8e16ce71 Mon Sep 17 00:00:00 2001 From: "Olle E. Johansson" Date: Tue, 15 Dec 2015 11:13:21 +0100 Subject: [PATCH 026/142] Fixing typo, adding copyright header --- modules/curl/curl_api.h | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/modules/curl/curl_api.h b/modules/curl/curl_api.h index cc610692211..362b625585c 100644 --- a/modules/curl/curl_api.h +++ b/modules/curl/curl_api.h @@ -1,4 +1,31 @@ -#ifndef _CURL_CPI_H_ +/* + * Copyright (C) 2015 Hugh Waite + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * Kamailio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/*! + * \file + * \brief Kamailio curl :: Core API include file + * \ingroup curl + * Module: \ref curl + */ +#ifndef _CURL_API_H_ #define _CURL_API_H_ #include "../../sr_module.h" From fc64249b6e4b8c6a2c2b2dc4175114dfb701c767 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Wed, 24 Jun 2015 22:19:24 +0200 Subject: [PATCH 027/142] modules/cfgt: trace config and save to file --- modules/cfgt/Makefile | 17 + modules/cfgt/cfgt.c | 45 +++ modules/cfgt/cfgt.h | 40 ++ modules/cfgt/cfgt_int.c | 797 +++++++++++++++++++++++++++++++++++++++ modules/cfgt/cfgt_int.h | 67 ++++ modules/cfgt/cfgt_json.c | 389 +++++++++++++++++++ modules/cfgt/cfgt_json.h | 38 ++ modules/cfgt/cfgt_mod.c | 112 ++++++ modules/cfgt/cfgt_mod.h | 29 ++ 9 files changed, 1534 insertions(+) create mode 100644 modules/cfgt/Makefile create mode 100644 modules/cfgt/cfgt.c create mode 100644 modules/cfgt/cfgt.h create mode 100644 modules/cfgt/cfgt_int.c create mode 100644 modules/cfgt/cfgt_int.h create mode 100644 modules/cfgt/cfgt_json.c create mode 100644 modules/cfgt/cfgt_json.h create mode 100644 modules/cfgt/cfgt_mod.c create mode 100644 modules/cfgt/cfgt_mod.h diff --git a/modules/cfgt/Makefile b/modules/cfgt/Makefile new file mode 100644 index 00000000000..7bfba621666 --- /dev/null +++ b/modules/cfgt/Makefile @@ -0,0 +1,17 @@ +# +# cfgt module makefile +# +# WARNING: do not run this directly, it should be run by the master Makefile + +include ../../Makefile.defs +auto_gen= +NAME=cfgt.so +LIBS= + +DEFS+=-DKAMAILIO_MOD_INTERFACE + +SERLIBPATH=../../lib +SER_LIBS+=$(SERLIBPATH)/kcore/kcore +SER_LIBS+=$(SERLIBPATH)/srutils/srutils + +include ../../Makefile.modules diff --git a/modules/cfgt/cfgt.c b/modules/cfgt/cfgt.c new file mode 100644 index 00000000000..256a259039a --- /dev/null +++ b/modules/cfgt/cfgt.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2015 Victor Seva (sipwise.com) + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * Kamailio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ +#include "cfgt_mod.h" +#include "cfgt.h" +#include "cfgt_int.h" + +/*! + * \brief cfgt module API export bind function + * \param api cfgt API + * \return 0 on success, -1 on failure + */ +int bind_cfgt(cfgt_api_t* api) +{ + if (!api) { + LM_ERR("invalid parameter value\n"); + return -1; + } + if (init_flag==0) { + LM_ERR("configuration error - trying to bind to cfgt module" + " before being initialized\n"); + return -1; + } + + api->cfgt_process_route = cfgt_process_route; + return 0; +} diff --git a/modules/cfgt/cfgt.h b/modules/cfgt/cfgt.h new file mode 100644 index 00000000000..f06a87e0c26 --- /dev/null +++ b/modules/cfgt/cfgt.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2015 Victor Seva (sipwise.com) + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * Kamailio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#ifndef _CFGT_BIND_H +#define _CFGT_BIND_H + +#include "../../sr_module.h" + +/* export not usable from scripts */ +#define NO_SCRIPT -1 + +typedef int (*cfgt_process_route_f)(struct sip_msg *msg, struct action *a); + +typedef struct cfgt_api { + cfgt_process_route_f cfgt_process_route; +} cfgt_api_t; + +/*! cfgt API export bind function */ +typedef int (*bind_cfgt_t)(cfgt_api_t* api); + +#endif diff --git a/modules/cfgt/cfgt_int.c b/modules/cfgt/cfgt_int.c new file mode 100644 index 00000000000..f5e87dbe944 --- /dev/null +++ b/modules/cfgt/cfgt_int.c @@ -0,0 +1,797 @@ +/** + * + * Copyright (C) 2015 Victor Seva (sipwise.com) + * + * This file is part of Kamailio, a free SIP server. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include +#include + +#include "../../events.h" +#include "../../lib/kcore/cmpapi.h" +#include "../../pvar.h" +#include "../../rpc.h" +#include "../../rpc_lookup.h" + +#include "cfgt_int.h" +#include "cfgt_json.h" + +static str _cfgt_route_prefix[] = { + str_init("start|"), + str_init("exit|"), + str_init("drop|"), + str_init("return|"), + {0, 0} +}; +cfgt_node_p _cfgt_node = NULL; +cfgt_hash_p _cfgt_uuid = NULL; +str cfgt_hdr_prefix = {"NGCP%", 5}; +str cfgt_basedir = {"/tmp", 4}; +int cfgt_mask = CFGT_DP_ALL; + +static int shm_str_hash_alloc(struct str_hash_table *ht, int size) +{ + ht->table = shm_malloc(sizeof(struct str_hash_head) * size); + + if (!ht->table) + return -1; + + ht->size = size; + return 0; +} + +static int _cfgt_init_hashtable(struct str_hash_table *ht) +{ + if (shm_str_hash_alloc(ht, CFGT_HASH_SIZE) != 0) + { + LM_ERR("Error allocating shared memory hashtable\n"); + return -1; + } + + str_hash_init(ht); + + return 0; +} + +int _cfgt_pv_parse(str *param, pv_elem_p *elem) +{ + if (param->s && param->len > 0) + { + if (pv_parse_format(param, elem)<0) + { + LM_ERR("malformed or non AVP %.*s AVP definition\n", + param->len, param->s); + return -1; + } + } + return 0; +} + +void _cfgt_remove_uuid(const str *uuid) +{ + struct str_hash_head *head; + struct str_hash_entry *entry, *back; + int i; + + if(_cfgt_uuid==NULL) return; + if(uuid) + { + lock_get(&_cfgt_uuid->lock); + entry = str_hash_get(&_cfgt_uuid->hash, uuid->s, uuid->len); + if(entry) + { + str_hash_del(entry); + shm_free(entry->key.s); + shm_free(entry); + LM_DBG("uuid[%.*s] removed from hash\n", uuid->len, uuid->s); + } + else LM_DBG("uuid[%.*s] not found in hash\n", uuid->len, uuid->s); + lock_release(&_cfgt_uuid->lock); + } + else + { + lock_get(&_cfgt_uuid->lock); + for(i=0; ihash.table+i; + clist_foreach_safe(head, entry, back, next) + { + LM_DBG("uuid[%.*s] removed from hash\n", + entry->key.len, entry->key.s); + str_hash_del(entry); + shm_free(entry->key.s); + shm_free(entry); + } + lock_release(&_cfgt_uuid->lock); + } + LM_DBG("remove all uuids. done\n"); + } +} + +int _cfgt_get_uuid_id(cfgt_node_p node) +{ + struct str_hash_entry *entry; + + if(_cfgt_uuid==NULL || node==NULL || node->uuid.len == 0) return -1; + lock_get(&_cfgt_uuid->lock); + entry = str_hash_get(&_cfgt_uuid->hash, node->uuid.s, node->uuid.len); + if(entry) + { + entry->u.n = entry->u.n + 1; + node->msgid = entry->u.n; + } + else + { + entry = shm_malloc(sizeof(struct str_hash_entry)); + if(entry==NULL) + { + lock_release(&_cfgt_uuid->lock); + LM_ERR("No shared memory left\n"); + return -1; + } + if (shm_str_dup(&entry->key, &node->uuid) != 0) + { + lock_release(&_cfgt_uuid->lock); + shm_free(entry); + LM_ERR("No shared memory left\n"); + return -1; + } + entry->u.n = 1; + node->msgid = 1; + LM_DBG("Add new entry[%.*s]\n", node->uuid.len, node->uuid.s); + str_hash_add(&_cfgt_uuid->hash, entry); + } + lock_release(&_cfgt_uuid->lock); + LM_DBG("msgid:[%d]\n", node->msgid); + return 1; +} + +int _cfgt_get_hdr_helper(struct sip_msg *msg, str *res, int mode) +{ + struct hdr_field *hf; + char *delimiter, *end; + str tmp = STR_NULL; + + if(msg==NULL || (mode==0 && res==NULL)) + return -1; + + /* we need to be sure we have parsed all headers */ + if(parse_headers(msg, HDR_EOH_F, 0)<0) + { + LM_ERR("error parsing headers\n"); + return -1; + } + + hf = msg->callid; + if(!hf) return 1; + + if(strncmp(hf->body.s, cfgt_hdr_prefix.s, cfgt_hdr_prefix.len)==0) + { + tmp.s = hf->body.s+cfgt_hdr_prefix.len; + delimiter = tmp.s-1; + LM_DBG("Prefix detected. delimiter[%c]\n", *delimiter); + if(mode==0) + { + end = strchr(tmp.s, *delimiter); + if(end) + { + tmp.len = end-tmp.s; + if(pkg_str_dup(res, &tmp)<0) + { + LM_ERR("error copying header\n"); + return -1; + } + LM_DBG("cfgtest uuid:[%.*s]\n", res->len, res->s); + return 0; + } + } + else + { + tmp.len = res->len; + LM_DBG("tmp[%.*s] res[%.*s]\n", tmp.len, tmp.s, res->len, res->s); + return STR_EQ(tmp, *res); + } + } + return 1; /* not found */ +} + +int _cfgt_get_hdr(struct sip_msg *msg, str *res) +{ + return _cfgt_get_hdr_helper(msg, res, 0); +} + +int _cfgt_cmp_hdr(struct sip_msg *msg, str *res) +{ + return _cfgt_get_hdr_helper(msg, res, 1); +} + +cfgt_node_p cfgt_create_node(struct sip_msg *msg) +{ + cfgt_node_p node; + + node = (cfgt_node_p) pkg_malloc(sizeof(cfgt_node_t)); + if(node==NULL) + { + LM_ERR("cannot allocate cfgtest msgnode\n"); + return node; + } + memset(node, 0, sizeof(cfgt_node_t)); + srjson_InitDoc(&node->jdoc, NULL); + if (msg) + { + node->msgid = msg->id; + LM_DBG("msgid:%d\n", node->msgid); + if(_cfgt_get_hdr(msg, &node->uuid)!=0 || &node->uuid.len==0) + { + LM_ERR("cannot get value of cfgtest uuid header!!\n"); + goto error; + } + } + node->jdoc.root = srjson_CreateObject(&node->jdoc); + if(node->jdoc.root==NULL) + { + LM_ERR("cannot create json root\n"); + goto error; + } + node->flow = srjson_CreateArray(&node->jdoc); + if(node->flow==NULL) + { + LM_ERR("cannot create json object\n"); + goto error; + } + srjson_AddItemToObject(&node->jdoc, node->jdoc.root, "flow\0", node->flow); + node->in = srjson_CreateArray(&node->jdoc); + if(node->in==NULL) + { + LM_ERR("cannot create json object\n"); + goto error; + } + srjson_AddItemToObject(&node->jdoc, node->jdoc.root, "sip_in\0", node->in); + node->out = srjson_CreateArray(&node->jdoc); + if(node->out==NULL) + { + LM_ERR("cannot create json object\n"); + goto error; + } + srjson_AddItemToObject(&node->jdoc, node->jdoc.root, "sip_out\0", node->out); + LM_DBG("node created\n"); + return node; + +error: + srjson_DestroyDoc(&node->jdoc); + pkg_free(node); + return NULL; +} + +void _cfgt_remove_node(cfgt_node_p node) +{ + if(!node) return; + srjson_DestroyDoc(&node->jdoc); + if(node->uuid.s) pkg_free(node->uuid.s); + while(node->flow_head) + { + node->route = node->flow_head; + node->flow_head = node->route->next; + pkg_free(node->route); + node->route = NULL; + } + pkg_free(node); +} + +int _cfgt_get_filename(int msgid, str uuid, str *dest, int *dir) +{ + int i, lid; + char buff_id[INT2STR_MAX_LEN]; + char *sid; + if(dest==NULL || uuid.len == 0) return -1; + + dest->len = cfgt_basedir.len + uuid.len; + if(cfgt_basedir.s[cfgt_basedir.len-1]!='/') + dest->len = dest->len + 1; + sid = sint2strbuf(msgid, buff_id, INT2STR_MAX_LEN, &lid); + dest->len += lid + 6; + dest->s = (char *) pkg_malloc((dest->len*sizeof(char)+1)); + if(dest->s==NULL) + { + LM_ERR("no more memory.\n"); + return -1; + } + strncpy(dest->s, cfgt_basedir.s, cfgt_basedir.len); + i = cfgt_basedir.len; + if(cfgt_basedir.s[cfgt_basedir.len-1]!='/') + { + strncpy(dest->s+i, "/", 1); + i = i + 1; + } + strncpy(dest->s+i, uuid.s, uuid.len); + i = i + uuid.len; (*dir) = i; + strncpy(dest->s+i, "\0", 1); + i = i + 1; + strncpy(dest->s+i, sid, lid); + i = i + lid; + strncpy(dest->s+i, ".json\0", 6); + return 0; +} + +int _cfgt_node2json(cfgt_node_p node) +{ + srjson_t *jobj; + + if(!node) return -1; + jobj = srjson_CreateStr(&node->jdoc, node->uuid.s, node->uuid.len); + if(jobj==NULL) + { + LM_ERR("cannot create json object\n"); + return -1; + } + srjson_AddItemToObject(&node->jdoc, node->jdoc.root, "uuid\0", jobj); + + jobj = srjson_CreateNumber(&node->jdoc, (double)node->msgid); + if(jobj==NULL) + { + LM_ERR("cannot create json object\n"); + return -1; + } + srjson_AddItemToObject(&node->jdoc, node->jdoc.root, "msgid\0", jobj); + return 0; +} + +void cfgt_save_node(cfgt_node_p node) +{ + FILE *fp; + str dest = STR_NULL; + int dir = 0; + if(_cfgt_get_filename(node->msgid, node->uuid, &dest, &dir)<0) + { + LM_ERR("can't build filename\n"); + return; + } + LM_DBG("dir [%s]\n", dest.s); + mkdir(dest.s, S_IRWXO|S_IXGRP|S_IRWXU); + dest.s[dir] = '/'; + fp = fopen(dest.s, "w"); + LM_DBG("file [%s]\n", dest.s); + if(fp) { + pkg_free(dest.s); + dest.s = srjson_Print(&node->jdoc, node->jdoc.root); + if(dest.s==NULL) + { + LM_ERR("Cannot get the json string\n"); + fclose(fp); + return; + } + if(fputs(dest.s, fp)<0){ + LM_ERR("failed writing to file\n"); + } + fclose(fp); + node->jdoc.free_fn(dest.s); + } + else { + LM_ERR("Can't open file [%s] to write\n", dest.s); + pkg_free(dest.s); + } +} + +void _cfgt_print_node(cfgt_node_p node, int json) +{ + char *buf = NULL; + cfgt_str_list_p route; + + if(!node) return; + if(node->flow_head) + { + route = node->flow_head; + while(route) + { + if(route == node->route) + LM_DBG("[--[%.*s][%d]--]\n", + route->s.len, route->s.s, route->type); + else LM_DBG("[%.*s][%d]\n", + route->s.len, route->s.s, route->type); + route = route->next; + } + } + else LM_DBG("flow:empty\n"); + if(json) { + buf = srjson_PrintUnformatted(&node->jdoc, node->jdoc.root); + if(buf==NULL) + { + LM_ERR("Cannot get the json string\n"); + return; + } + LM_DBG("node[%p]: id:[%d] uuid:[%.*s] info:[%s]\n", + node, node->msgid, node->uuid.len, node->uuid.s, buf); + node->jdoc.free_fn(buf); + } +} + +int _cfgt_set_dump(struct sip_msg *msg, cfgt_node_p node, str *flow) +{ + srjson_t *f, *vars; + + if(node==NULL || flow == NULL) return -1; + vars = srjson_CreateObject(&node->jdoc); + if(vars==NULL) + { + LM_ERR("cannot create json object\n"); + return -1; + } + if(cfgt_get_json(msg, 30, &node->jdoc, vars)<0) + { + LM_ERR("cannot get var info\n"); + return -1; + } + f = srjson_CreateObject(&node->jdoc); + if(f==NULL) + { + LM_ERR("cannot create json object\n"); + srjson_Delete(&node->jdoc, vars); + return -1; + } + srjson_AddStrItemToObject(&node->jdoc, f, + flow->s, flow->len, vars); + srjson_AddItemToArray(&node->jdoc, node->flow, f); + LM_DBG("node[%.*s] flow created\n", flow->len, flow->s); + return 0; +} + +void _cfgt_set_type(cfgt_str_list_p route, struct action *a) +{ + switch(a->type) + { + case DROP_T: + if(a->val[1].u.number&DROP_R_F) { + route->type = CFGT_DROP_D; + LM_DBG("set[%.*s]->CFGT_DROP_D\n", route->s.len, route->s.s); + } + if(a->val[1].u.number&RETURN_R_F){ + route->type = CFGT_DROP_R; + LM_DBG("set[%.*s]->CFGT_DROP_R\n", route->s.len, route->s.s); + } + else { + route->type = CFGT_DROP_E; + LM_DBG("set[%.*s]->CFGT_DROP_E\n", route->s.len, route->s.s); + } + break; + case ROUTE_T: + route->type = CFGT_ROUTE; + LM_DBG("set[%.*s]->CFGT_ROUTE\n", route->s.len, route->s.s); + break; + default: + if(route->type!=CFGT_DROP_E) + { + route->type = CFGT_DROP_R; + LM_DBG("[%.*s] no relevant action: CFGT_DROP_R[%d]\n", + route->s.len, route->s.s, a->type); + } + else + { + LM_DBG("[%.*s] already set to CFGT_DROP_E[%d]\n", + route->s.len, route->s.s, a->type); + } + break; + } +} + +int _cfgt_add_routename(cfgt_node_p node, struct action *a, + str *routename) +{ + cfgt_str_list_p route; + int ret = 0; + + if(!node->route) /* initial */ + { + node->route = pkg_malloc(sizeof(cfgt_str_list_t)); + if(!node->route) + { + LM_ERR("No more pkg mem\n"); + return -1; + } + memset(node->route, 0, sizeof(cfgt_str_list_t)); + node->flow_head = node->route; + node->route->type = CFGT_ROUTE; + ret = 1; + } + else + { + LM_DBG("actual routename:[%.*s][%d]\n", node->route->s.len, + node->route->s.s, node->route->type); + if(node->route->prev) + LM_DBG("prev routename:[%.*s][%d]\n", node->route->prev->s.len, + node->route->prev->s.s, node->route->prev->type); + if(node->route->next) + LM_DBG("next routename:[%.*s][%d]\n", node->route->next->s.len, + node->route->next->s.s, node->route->next->type); + if(STR_EQ(*routename, node->route->s)) + { + LM_DBG("same route\n"); + _cfgt_set_type(node->route, a); + return 2; + } + else if(node->route->prev && + STR_EQ(*routename, node->route->prev->s)) + { + LM_DBG("back to route[%.*s]\n", node->route->prev->s.len, + node->route->prev->s.s); + _cfgt_set_type(node->route->prev, a); + return 3; + } + route = pkg_malloc(sizeof(cfgt_str_list_t)); + if(!route) + { + LM_ERR("No more pkg mem\n"); + return -1; + } + memset(route, 0, sizeof(cfgt_str_list_t)); + route->prev = node->route; + node->route->next = route; + node->route = route; + _cfgt_set_type(node->route, a); + } + node->route->s.s = routename->s; + node->route->s.len = routename->len; + LM_DBG("add[%d] route:[%.*s]\n", ret, node->route->s.len, node->route->s.s); + _cfgt_print_node(node, 0); + return ret; +} + +void _cfgt_del_routename(cfgt_node_p node) +{ + if(node->route->next!=NULL) { + LM_ERR("wtf!! route->next[%p] not null!!\n", node->route->next); + _cfgt_print_node(node, 0); + } + LM_DBG("del route[%.*s]\n", node->route->s.len, node->route->s.s); + node->route = node->route->prev; + pkg_free(node->route->next); + node->route->next = NULL; +} +/* dest has to be freed */ +int _cfgt_node_get_flowname(cfgt_str_list_p route, int *indx, str *dest) +{ + int i; + if(route==NULL) return -1; + LM_DBG("routename:[%.*s][%d]\n", route->s.len, route->s.s, + route->type); + if(indx) i = *indx; + else i = route->type-1; + if(str_append(&_cfgt_route_prefix[i], + &route->s, dest)<0) + { + LM_ERR("Cannot create route name\n"); + return -1; + } + return 0; +} + +int cfgt_process_route(struct sip_msg *msg, struct action *a) +{ + str routename; + int ret = -1; + int indx = 0; + str flowname = STR_NULL; + if(!_cfgt_node) { + LM_ERR("node empty\n"); + return -1; + } + if (a->rname==NULL) { + LM_DBG("no routename. type:%d\n", a->type); + return 0; + } + LM_DBG("route from action:[%s]\n", a->rname); + routename.s = a->rname; routename.len = strlen(a->rname); + switch(_cfgt_add_routename(_cfgt_node, a, &routename)) + { + case 2: /* same name */ + return 0; + case 1: /* initial */ + LM_DBG("Initial route[%.*s]. dump vars\n", + _cfgt_node->route->s.len, _cfgt_node->route->s.s); + if(_cfgt_node_get_flowname(_cfgt_node->route, &indx, &flowname)<0) + { + LM_ERR("cannot create flowname\n"); + return -1; + } + ret = _cfgt_set_dump(msg, _cfgt_node, &flowname); + break; + case 0: /* new */ + LM_DBG("Change from[%.*s] route to route[%.*s]. dump vars\n", + _cfgt_node->route->prev->s.len, _cfgt_node->route->prev->s.s, + _cfgt_node->route->s.len, _cfgt_node->route->s.s); + if(_cfgt_node_get_flowname(_cfgt_node->route, &indx, &flowname)<0) + { + LM_ERR("cannot create flowname\n"); + return -1; + } + ret = _cfgt_set_dump(msg, _cfgt_node, &flowname); + break; + case 3: /* back to previous */ + if(_cfgt_node_get_flowname(_cfgt_node->route, 0, &flowname)<0) + { + LM_ERR("cannot create flowname\n"); + return -1; + } + ret = _cfgt_set_dump(msg, _cfgt_node, &flowname); + _cfgt_del_routename(_cfgt_node); + break; + default: + return -1; + } + if(flowname.s) pkg_free(flowname.s); + return ret; +} + +/* +TODO: +- parse first line, check if is SIP +- parse for header cfgtest +*/ +int cfgt_msgin(void *data) +{ + srjson_t *jobj; + str *buf = (str *) data; + if(buf==NULL) return 0; + if(_cfgt_node) { + cfgt_save_node(_cfgt_node); + _cfgt_remove_node(_cfgt_node); + LM_DBG("node removed\n"); + _cfgt_node = NULL; + } + LM_DBG("msg in:{%.*s}\n", buf->len, buf->s); + _cfgt_node = cfgt_create_node(NULL); + if(_cfgt_node) + { + jobj = srjson_CreateStr(&_cfgt_node->jdoc, buf->s, buf->len); + if(jobj==NULL) + { + LM_ERR("cannot create json object\n"); + return -1; + } + srjson_AddItemToArray(&_cfgt_node->jdoc, _cfgt_node->in, jobj); + return 0; + } + LM_ERR("_cfgt_node empty\n"); + return -1; +} + +int cfgt_pre(struct sip_msg *msg, unsigned int flags, void *bar) { + str unknown = {"unknown", 7}; + + if(_cfgt_node) + { + if (_cfgt_node->msgid == 0) + { + LM_DBG("new node\n"); + if(_cfgt_get_hdr(msg, &_cfgt_node->uuid)!=0 || + _cfgt_node->uuid.len==0) + { + LM_ERR("cannot get value of cfgtest uuid header." + " Using unknown\n"); + pkg_str_dup(&_cfgt_node->uuid, &unknown); + } + return _cfgt_get_uuid_id(_cfgt_node); + } + else + { + LM_DBG("_cfgt_node->uuid:[%.*s]\n", _cfgt_node->uuid.len, + _cfgt_node->uuid.s); + if(_cfgt_cmp_hdr(msg, &_cfgt_node->uuid)) + { + LM_DBG("same uuid\n"); + return 1; + } + else { + LM_DBG("different uuid\n"); + } + } + } + else { LM_ERR("node empty??\n"); } + _cfgt_node = cfgt_create_node(msg); + if(_cfgt_node) { + LM_DBG("node created\n"); + return 1; + } + return -1; +} +int cfgt_post(struct sip_msg *msg, unsigned int flags, void *bar) { + str flowname = STR_NULL; + + if(_cfgt_node) { + LM_DBG("dump last flow\n"); + if(_cfgt_node_get_flowname(_cfgt_node->route, 0, &flowname)<0) + LM_ERR("cannot create flowname\n"); + else _cfgt_set_dump(msg, _cfgt_node, &flowname); + if(flowname.s) pkg_free(flowname.s); + cfgt_save_node(_cfgt_node); + } + return 1; +} + +int cfgt_msgout(void *data) +{ + srjson_t *jobj; + str *buf = (str *) data; + if(buf==NULL) return 0; + LM_DBG("msg out:{%.*s}\n", buf->len, buf->s); + + if(_cfgt_node) + { + jobj = srjson_CreateStr(&_cfgt_node->jdoc, buf->s, buf->len); + if(jobj==NULL) + { + LM_ERR("cannot create json object\n"); + return -1; + } + srjson_AddItemToArray(&_cfgt_node->jdoc, _cfgt_node->out, jobj); + return 0; + } + LM_ERR("node empty\n"); + return -1; +} + +/** + * + */ +static const char* cfgt_rpc_mask_doc[2] = { + "Specify module mask", + 0 +}; + +static void cfgt_rpc_mask(rpc_t* rpc, void* ctx){ + int mask = CFGT_DP_ALL; + + if (rpc->scan(ctx, "*d", &mask) != 1) + { + rpc->fault(ctx, 500, "invalid parameters"); + return; + } + cfgt_mask = mask; + rpc->add(ctx, "s", "200 ok"); +} + +rpc_export_t cfgt_rpc[] = { + {"dbg.mask", cfgt_rpc_mask, cfgt_rpc_mask_doc, 0}, + {0, 0, 0, 0} +}; + +int cfgt_init(void) +{ + if (rpc_register_array(cfgt_rpc)!=0) + { + LM_ERR("failed to register RPC commands\n"); + return -1; + } + _cfgt_uuid = shm_malloc(sizeof(cfgt_hash_t)); + if(_cfgt_uuid==NULL) + { + LM_ERR("Cannot allocate shared memory\n"); + return -1; + } + if(!lock_init(&_cfgt_uuid->lock)) + { + LM_ERR("cannot init the lock\n"); + shm_free(_cfgt_uuid); + _cfgt_uuid = NULL; + return -1; + } + if(_cfgt_init_hashtable(&_cfgt_uuid->hash)<0) + return -1; + sr_event_register_cb(SREV_NET_DATA_IN, cfgt_msgin); + sr_event_register_cb(SREV_NET_DATA_OUT, cfgt_msgout); + return 0; +} diff --git a/modules/cfgt/cfgt_int.h b/modules/cfgt/cfgt_int.h new file mode 100644 index 00000000000..3587264bcbd --- /dev/null +++ b/modules/cfgt/cfgt_int.h @@ -0,0 +1,67 @@ +/** + * + * Copyright (C) 2015 Victor Seva (sipwise.com) + * + * This file is part of Kamailio, a free SIP server. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#ifndef _CFGT_INT_H_ +#define _CFGT_INT_H_ + +#include "../../lib/srutils/srjson.h" +#include "../../locking.h" +#include "../../route_struct.h" +#include "../../str_hash.h" + +#define CFGT_HASH_SIZE 32 + +enum _cfgt_action_type { + CFGT_ROUTE=1, + CFGT_DROP_E, CFGT_DROP_D, CFGT_DROP_R +}; + +typedef struct _cfgt_hash +{ + gen_lock_t lock; + struct str_hash_table hash; + str save_uuid; /* uuid to be save */ +} cfgt_hash_t, *cfgt_hash_p; + +typedef struct _cfgt_str_list +{ + str s; + enum _cfgt_action_type type; + struct _cfgt_str_list *next, *prev; +} cfgt_str_list_t, *cfgt_str_list_p; + +typedef struct _cfgt_node +{ + srjson_doc_t jdoc; + str uuid; + int msgid; + cfgt_str_list_p flow_head; + cfgt_str_list_p route; + srjson_t *in, *out, *flow; + struct _cfgt_node *next, *prev; +} cfgt_node_t, *cfgt_node_p; + +int cfgt_init(void); +cfgt_node_p cfgt_create_node(struct sip_msg *msg); +int cfgt_process_route(struct sip_msg *msg, struct action *a); +int cfgt_pre(struct sip_msg *msg, unsigned int flags, void *bar); +int cfgt_post(struct sip_msg *msg, unsigned int flags, void *bar); +#endif diff --git a/modules/cfgt/cfgt_json.c b/modules/cfgt/cfgt_json.c new file mode 100644 index 00000000000..b4c235924b4 --- /dev/null +++ b/modules/cfgt/cfgt_json.c @@ -0,0 +1,389 @@ +/** + * + * Copyright (C) 2013-2015 Victor Seva (sipwise.com) + * + * This file is part of Kamailio, a free SIP server. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include + +#include "../../pvar.h" +#include "../../mem/shm_mem.h" +#include "../../xavp.h" +#include "../pv/pv_xavp.h" + +#include "cfgt_json.h" + +int _cfgt_get_array_avp_vals(struct sip_msg *msg, + pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobj, + str *item_name) +{ + struct usr_avp *avp; + unsigned short name_type; + int_str avp_name; + int_str avp_value; + struct search_state state; + srjson_t *jobjt; + memset(&state, 0, sizeof(struct search_state)); + + if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0) + { + LM_ERR("invalid name\n"); + return -1; + } + *jobj = srjson_CreateArray(jdoc); + if(*jobj==NULL) + { + LM_ERR("cannot create json object\n"); + return -1; + } + if ((avp=search_first_avp(name_type, avp_name, &avp_value, &state))==0) + { + goto ok; + } + do + { + if(avp->flags & AVP_VAL_STR) + { + jobjt = srjson_CreateStr(jdoc, avp_value.s.s, avp_value.s.len); + if(jobjt==NULL) + { + LM_ERR("cannot create json object\n"); + return -1; + } + } else { + jobjt = srjson_CreateNumber(jdoc, avp_value.n); + if(jobjt==NULL) + { + LM_ERR("cannot create json object\n"); + return -1; + } + } + srjson_AddItemToArray(jdoc, *jobj, jobjt); + } while ((avp=search_next_avp(&state, &avp_value))!=0); +ok: + item_name->s = avp_name.s.s; + item_name->len = avp_name.s.len; + return 0; +} +#define CFGT_XAVP_DUMP_SIZE 32 +static str* _cfgt_xavp_dump[CFGT_XAVP_DUMP_SIZE]; +int _cfgt_xavp_dump_lookup(pv_param_t *param) +{ + unsigned int i = 0; + pv_xavp_name_t *xname; + + if(param==NULL) + return -1; + + xname = (pv_xavp_name_t*)param->pvn.u.dname; + + while(_cfgt_xavp_dump[i]!=NULL&&ilen==xname->name.len) + { + if(strncmp(_cfgt_xavp_dump[i]->s, xname->name.s, xname->name.len)==0) + return 1; /* already dump before */ + } + i++; + } + if(i==CFGT_XAVP_DUMP_SIZE) + { + LM_WARN("full _cfgt_xavp_dump cache array\n"); + return 0; /* end cache names */ + } + _cfgt_xavp_dump[i] = &xname->name; + return 0; +} + +void _cfgt_get_obj_xavp_val(sr_xavp_t *avp, srjson_doc_t *jdoc, srjson_t **jobj) +{ + static char _pv_xavp_buf[128]; + int result = 0; + + switch(avp->val.type) { + case SR_XTYPE_NULL: + *jobj = srjson_CreateNull(jdoc); + break; + case SR_XTYPE_INT: + *jobj = srjson_CreateNumber(jdoc, avp->val.v.i); + break; + case SR_XTYPE_STR: + *jobj = srjson_CreateStr(jdoc, avp->val.v.s.s, avp->val.v.s.len); + break; + case SR_XTYPE_TIME: + result = snprintf(_pv_xavp_buf, 128, "%lu", (long unsigned)avp->val.v.t); + break; + case SR_XTYPE_LONG: + result = snprintf(_pv_xavp_buf, 128, "%ld", (long unsigned)avp->val.v.l); + break; + case SR_XTYPE_LLONG: + result = snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll); + break; + case SR_XTYPE_XAVP: + result = snprintf(_pv_xavp_buf, 128, "<>", avp->val.v.xavp); + break; + case SR_XTYPE_DATA: + result = snprintf(_pv_xavp_buf, 128, "<>", avp->val.v.data); + break; + default: + LM_WARN("unknown data type\n"); + *jobj = srjson_CreateNull(jdoc); + } + if(result<0) + { + LM_ERR("cannot convert to str\n"); + *jobj = srjson_CreateNull(jdoc); + } + else if(*jobj==NULL) + { + *jobj = srjson_CreateStr(jdoc, _pv_xavp_buf, 128); + } +} + +int _cfgt_get_obj_avp_vals(str name, sr_xavp_t *xavp, srjson_doc_t *jdoc, srjson_t **jobj) +{ + sr_xavp_t *avp = NULL; + srjson_t *jobjt = NULL; + + *jobj = srjson_CreateArray(jdoc); + if(*jobj==NULL) + { + LM_ERR("cannot create json object\n"); + return -1; + } + avp = xavp; + while(avp!=NULL&&!STR_EQ(avp->name,name)) + { + avp = avp->next; + } + while(avp!=NULL) + { + _cfgt_get_obj_xavp_val(avp, jdoc, &jobjt); + srjson_AddItemToArray(jdoc, *jobj, jobjt); + jobjt = NULL; + avp = xavp_get_next(avp); + } + + return 0; +} + +int _cfgt_get_obj_xavp_vals(struct sip_msg *msg, + pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobjr, + str *item_name) +{ + pv_xavp_name_t *xname = (pv_xavp_name_t*)param->pvn.u.dname; + sr_xavp_t *xavp = NULL; + sr_xavp_t *avp = NULL; + srjson_t *jobj = NULL; + srjson_t *jobjt = NULL; + struct str_list *keys; + struct str_list *k; + + *jobjr = srjson_CreateArray(jdoc); + if(*jobjr==NULL) + { + LM_ERR("cannot create json object\n"); + return -1; + } + + item_name->s = xname->name.s; + item_name->len = xname->name.len; + xavp = xavp_get_by_index(&xname->name, 0, NULL); + if(xavp==NULL) + { + return 0; /* empty */ + } + + do + { + if(xavp->val.type==SR_XTYPE_XAVP) + { + avp = xavp->val.v.xavp; + jobj = srjson_CreateObject(jdoc); + if(jobj==NULL) + { + LM_ERR("cannot create json object\n"); + return -1; + } + keys = xavp_get_list_key_names(xavp); + if(keys!=NULL) + { + do + { + _cfgt_get_obj_avp_vals(keys->s, avp, jdoc, &jobjt); + srjson_AddStrItemToObject(jdoc, jobj, keys->s.s, + keys->s.len, jobjt); + k = keys; + keys = keys->next; + pkg_free(k); + jobjt = NULL; + }while(keys!=NULL); + } + } + if(jobj!=NULL) + { + srjson_AddItemToArray(jdoc, *jobjr, jobj); + jobj = NULL; + } + }while((xavp = xavp_get_next(xavp))!=0); + + return 0; +} + +int cfgt_get_json(struct sip_msg* msg, unsigned int mask, srjson_doc_t *jdoc, + srjson_t *head) +{ + int i; + pv_value_t value; + pv_cache_t **_pv_cache = pv_cache_get_table(); + pv_cache_t *el = NULL; + srjson_t *jobj = NULL; + str item_name = STR_NULL; + static char iname[128]; + + if(_pv_cache==NULL) + { + LM_ERR("cannot access pv_cache\n"); + return -1; + } + if(jdoc==NULL){ + LM_ERR("jdoc is null\n"); + return -1; + } + if(head==NULL){ + LM_ERR("head is null\n"); + return -1; + } + + memset(_cfgt_xavp_dump, 0, sizeof(str*)*CFGT_XAVP_DUMP_SIZE); + for(i=0;ispec.type==PVT_AVP|| + el->spec.type==PVT_SCRIPTVAR|| + el->spec.type==PVT_XAVP|| + el->spec.type==PVT_OTHER)|| + !((el->spec.type==PVT_AVP&&mask&CFGT_DP_AVP)|| + (el->spec.type==PVT_XAVP&&mask&CFGT_DP_XAVP)|| + (el->spec.type==PVT_SCRIPTVAR&&mask&CFGT_DP_SCRIPTVAR)|| + (el->spec.type==PVT_OTHER&&mask&CFGT_DP_OTHER))|| + (el->spec.trans!=NULL)) + { + el = el->next; + continue; + } + jobj = NULL; + item_name.len = 0; + item_name.s = 0; + iname[0] = '\0'; + if(el->spec.type==PVT_AVP) + { + if(el->spec.pvp.pvi.type==PV_IDX_ALL|| + (el->spec.pvp.pvi.type==PV_IDX_INT&&el->spec.pvp.pvi.u.ival!=0)) + { + el = el->next; + continue; + } + else + { + if(_cfgt_get_array_avp_vals(msg, &el->spec.pvp, jdoc, &jobj, &item_name)!=0) + { + LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s); + el = el->next; + continue; + } + if(srjson_GetArraySize(jdoc, jobj)==0 && !(mask&CFGT_DP_NULL)) + { + el = el->next; + continue; + } + snprintf(iname, 128, "$avp(%.*s)", item_name.len, item_name.s); + } + } + else if(el->spec.type==PVT_XAVP) + { + if(_cfgt_xavp_dump_lookup(&el->spec.pvp)!=0) + { + el = el->next; + continue; + } + if(_cfgt_get_obj_xavp_vals(msg, &el->spec.pvp, jdoc, &jobj, &item_name)!=0) + { + LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s); + el = el->next; + continue; + } + if(srjson_GetArraySize(jdoc, jobj)==0 && !(mask&CFGT_DP_NULL)) + { + el = el->next; + continue; + } + snprintf(iname, 128, "$xavp(%.*s)", item_name.len, item_name.s); + } + else + { + if(pv_get_spec_value(msg, &el->spec, &value)!=0) + { + LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s); + el = el->next; + continue; + } + if(value.flags&(PV_VAL_NULL|PV_VAL_EMPTY|PV_VAL_NONE)) + { + if(mask&CFGT_DP_NULL) + { + jobj = srjson_CreateNull(jdoc); + } + else + { + el = el->next; + continue; + } + }else if(value.flags&(PV_VAL_INT)){ + jobj = srjson_CreateNumber(jdoc, value.ri); + }else if(value.flags&(PV_VAL_STR)){ + jobj = srjson_CreateStr(jdoc, value.rs.s, value.rs.len); + }else { + LM_WARN("el->pvname[%.*s] value[%d] unhandled\n", el->pvname.len, el->pvname.s, + value.flags); + el = el->next; + continue; + } + if(jobj==NULL) + { + LM_ERR("el->pvname[%.*s] empty json object\n", el->pvname.len, + el->pvname.s); + goto error; + } + snprintf(iname, 128, "%.*s", el->pvname.len, el->pvname.s); + } + if(jobj!=NULL) + { + srjson_AddItemToObject(jdoc, head, iname, jobj); + } + el = el->next; + } + } + return 0; + +error: + srjson_Delete(jdoc, head); + return -1; +} \ No newline at end of file diff --git a/modules/cfgt/cfgt_json.h b/modules/cfgt/cfgt_json.h new file mode 100644 index 00000000000..7ab10b4df1c --- /dev/null +++ b/modules/cfgt/cfgt_json.h @@ -0,0 +1,38 @@ +/** + * + * Copyright (C) 2013-2015 Victor Seva (sipwise.com) + * + * This file is part of Kamailio, a free SIP server. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _CFGT_JSON_H +#define _CFGT_JSON_H + +#include "../../lib/srutils/srjson.h" +#include "../../route_struct.h" + +#define CFGT_DP_NULL 1 +#define CFGT_DP_AVP 2 +#define CFGT_DP_SCRIPTVAR 4 +#define CFGT_DP_XAVP 8 +#define CFGT_DP_OTHER 16 +#define CFGT_DP_ALL 31 + +int cfgt_get_json(struct sip_msg* msg, unsigned int mask, srjson_doc_t *jdoc, + srjson_t *head); +#endif diff --git a/modules/cfgt/cfgt_mod.c b/modules/cfgt/cfgt_mod.c new file mode 100644 index 00000000000..6b5ad42877a --- /dev/null +++ b/modules/cfgt/cfgt_mod.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2015 Victor Seva (sipwise.com) + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * Kamailio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "../../events.h" +#include "../../script_cb.h" +#include "../../sr_module.h" + +#include "cfgt_mod.h" +#include "cfgt_int.h" +#include "cfgt_json.h" +#include "cfgt.h" + +MODULE_VERSION + +static int mod_init(void); /*!< Module initialization function */ +static void destroy(void); /*!< Module destroy function */ +static int child_init(int rank); /*!< Per-child init function */ + +extern int bind_cfgt(cfgt_api_t* api); + +/*! flag to protect against wrong initialization */ +unsigned int init_flag = 0; +extern int cfgt_mask; +extern str cfgt_basedir; +extern str cfgt_hdr_prefix; + +/*! \brief + * Exported functions + */ +static cmd_export_t cmds[] = { + {"cfgt_bind_cfgt", (cmd_function)bind_cfgt, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0} +}; + +/*! \brief + * Exported parameters + */ +static param_export_t params[] = { + {"basedir", PARAM_STR, &cfgt_basedir}, + {"mask", INT_PARAM, &cfgt_mask }, + {"callid_prefix", PARAM_STR, &cfgt_hdr_prefix }, + {0, 0, 0} +}; + +struct module_exports exports = { + "cfgt", + DEFAULT_DLFLAGS, /*!< dlopen flags */ + cmds, /*!< Exported functions */ + params, /*!< Export parameters */ + 0, /*!< exported statistics */ + 0, /*!< exported MI functions */ + 0, /*!< exported pseudo-variables */ + 0, /*!< extra processes */ + mod_init, /*!< Module initialization function */ + 0, /*!< Response function */ + destroy, /*!< Destroy function */ + child_init /*!< Child initialization function */ +}; + +/*! \brief + * Module initialization function + */ +static int mod_init(void) +{ + unsigned int ALL = REQUEST_CB+FAILURE_CB+ONREPLY_CB + +BRANCH_CB+ONSEND_CB+ERROR_CB+LOCAL_CB+EVENT_CB+BRANCH_FAILURE_CB; + if(cfgt_init()<0) return -1; + if (register_script_cb(cfgt_pre, PRE_SCRIPT_CB|ALL, 0) != 0) + { + LM_ERR("could not insert PRE_SCRIPT callback"); + return -1; + } + if (register_script_cb(cfgt_post, POST_SCRIPT_CB|ALL, 0) != 0) + { + LM_ERR("could not insert POST_SCRIPT callback"); + return -1; + } + + init_flag = 1; + return 0; +} + +static int child_init(int _rank) +{ + return 0; +} + +/*! \brief + * Module destroy function + */ +static void destroy(void) +{ +} diff --git a/modules/cfgt/cfgt_mod.h b/modules/cfgt/cfgt_mod.h new file mode 100644 index 00000000000..1d8323d03e1 --- /dev/null +++ b/modules/cfgt/cfgt_mod.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 Victor Seva (sipwise.com) + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * Kamailio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#ifndef _CFGT_MOD_H +#define _CFGT_MOD_H + +/*! flag to protect against wrong initialization */ +extern unsigned int init_flag; + +#endif From b8309bd5fef4647c13cbabae768c47fdb7c8bc59 Mon Sep 17 00:00:00 2001 From: "Olle E. Johansson" Date: Tue, 15 Dec 2015 11:25:41 +0100 Subject: [PATCH 028/142] curl Update TODO.txt after Hugh's contribution --- modules/curl/TODO.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/curl/TODO.txt b/modules/curl/TODO.txt index 0a728fdbd61..2bb134f099d 100644 --- a/modules/curl/TODO.txt +++ b/modules/curl/TODO.txt @@ -53,3 +53,6 @@ The curl module - todo $curlcon == connection $curl == URL $curlres == result + +- API for other modules - done by Hugh Waite + - Needs documentation From 9ee0bd917f1e6a2b1fc9f116ea22584388a5e0d8 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Tue, 15 Dec 2015 10:24:13 +0100 Subject: [PATCH 029/142] modules/cfgt: add initial documentation --- modules/cfgt/README | 126 +++++++++++++++++++++++++ modules/cfgt/doc/Makefile | 4 + modules/cfgt/doc/cfgt.xml | 36 ++++++++ modules/cfgt/doc/cfgt_admin.xml | 158 ++++++++++++++++++++++++++++++++ 4 files changed, 324 insertions(+) create mode 100644 modules/cfgt/README create mode 100644 modules/cfgt/doc/Makefile create mode 100644 modules/cfgt/doc/cfgt.xml create mode 100644 modules/cfgt/doc/cfgt_admin.xml diff --git a/modules/cfgt/README b/modules/cfgt/README new file mode 100644 index 00000000000..a3be5ffac22 --- /dev/null +++ b/modules/cfgt/README @@ -0,0 +1,126 @@ +cfgt Module + +Victor Seva + + sipwise.com + +Edited by + +Victor Seva + + + + Copyright © 2015 Victor Seva (sipwise.com) + __________________________________________________________________ + + Table of Contents + + 1. Admin Guide + + 1. Overview + 2. Dependencies + + 2.1. Kamailio Modules + 2.2. External Libraries or Applications + + 3. Parameters + + 3.1. basedir (string) + 3.2. mask (int) + 3.3. callid_prefix (string) + + List of Examples + + 1.1. Set cfgtrace parameter + 1.2. Set mask parameter + 1.3. Set callid_prefix parameter + +Chapter 1. Admin Guide + + Table of Contents + + 1. Overview + 2. Dependencies + + 2.1. Kamailio Modules + 2.2. External Libraries or Applications + + 3. Parameters + + 3.1. basedir (string) + 3.2. mask (int) + 3.3. callid_prefix (string) + +1. Overview + + This module provides a report of the way Kamailio SIP Server Platform + configuration has been executed as part of a unit test for different + SIP scenarios. + + In order to identify defferent scenarios a prefix string should be used + at Call-ID header. + +2. Dependencies + + 2.1. Kamailio Modules + 2.2. External Libraries or Applications + +2.1. Kamailio Modules + + The following modules must be loaded before this module: + * None. + +2.2. External Libraries or Applications + + The following libraries or applications must be installed before + running Kamailio with this module loaded: + * None. + +3. Parameters + + 3.1. basedir (string) + 3.2. mask (int) + 3.3. callid_prefix (string) + +3.1. basedir (string) + + Control where the config reports should be stored. The dir must exists + and Kamailio SIP Server Platform must have perms to write on it. + + Default value is "/tmp". + + Example 1.1. Set cfgtrace parameter +... +modparam("cfgt", "basedir", "/var/run/kamailio/cfgtest") +... + +3.2. mask (int) + + mask - Control the type of vars it should display in the report: + * 1 - dump null values + * 2 - dump avp vars + * 4 - dump script vars + * 8 - dump xavp vars + * 16 - dump DP_OTHER vars + * 32 - dump ALL vars + + Default value is "32" (ALL). + + Example 1.2. Set mask parameter +... +# dump xavp(8) and avp(4) vars +modparam("cfgt", "mask", 12) +... + +3.3. callid_prefix (string) + + Prefix used to indentify test scenario messages. Last char of the + string will be used as delimiter. + + Default value is "NGCP%" (using "%" as delimiter). + + Example 1.3. Set callid_prefix parameter +... +# using '%' as delimiter +modparam("cfgt", "callid_prefix", "TEST-ID%") +... diff --git a/modules/cfgt/doc/Makefile b/modules/cfgt/doc/Makefile new file mode 100644 index 00000000000..5ff9aaec00f --- /dev/null +++ b/modules/cfgt/doc/Makefile @@ -0,0 +1,4 @@ +docs = cfgt.xml + +docbook_dir = ../../../docbook +include $(docbook_dir)/Makefile.module diff --git a/modules/cfgt/doc/cfgt.xml b/modules/cfgt/doc/cfgt.xml new file mode 100644 index 00000000000..dbbdbb8952c --- /dev/null +++ b/modules/cfgt/doc/cfgt.xml @@ -0,0 +1,36 @@ + + + +%docentities; + +]> + + + + cfgt Module + &kamailioname; + + + Victor + Seva + sipwise.com + + + Victor + Seva + linuxmaniac@torreviejawireless.org + + + + 2015 + Victor Seva (sipwise.com) + + + + + + + diff --git a/modules/cfgt/doc/cfgt_admin.xml b/modules/cfgt/doc/cfgt_admin.xml new file mode 100644 index 00000000000..07b8ea4f66f --- /dev/null +++ b/modules/cfgt/doc/cfgt_admin.xml @@ -0,0 +1,158 @@ + + + +%docentities; + +]> + + + + + + &adminguide; + +
+ Overview + + This module provides a report of the way &kamailioname; configuration + has been executed as part of a unit test for different + SIP scenarios. + + + In order to identify defferent scenarios a prefix string should be + used at Call-ID header. + +
+
+ Dependencies +
+ &kamailio; Modules + + The following modules must be loaded before this module: + + + + None. + + + + +
+
+ External Libraries or Applications + + The following libraries or applications must be installed before running + &kamailio; with this module loaded: + + + + None. + + + + +
+
+
+ Parameters +
+ <varname>basedir</varname> (string) + + Control where the config reports should be stored. The dir must + exists and &kamailioname; must have perms to write on it. + + + + Default value is /tmp. + + + + Set <varname>cfgtrace</varname> parameter + +... +modparam("cfgt", "basedir", "/var/run/kamailio/cfgtest") +... + + +
+ +
+ <varname>mask</varname> (int) + + mask - Control the type of vars it should + display in the report: + + + + 1 - dump null values + + + 2 - dump avp vars + + + 4 - dump script vars + + + 8 - dump xavp vars + + + 16 - dump DP_OTHER vars + + + 32 - dump ALL vars + + + + + + Default value is 32 (ALL). + + + + Set <varname>mask</varname> parameter + +... +# dump xavp(8) and avp(4) vars +modparam("cfgt", "mask", 12) +... + + +
+ +
+ <varname>callid_prefix</varname> (string) + + Prefix used to indentify test scenario messages. Last char of the + string will be used as delimiter. + + + + Default value is NGCP% + (using % as delimiter). + + + + Set <varname>callid_prefix</varname> parameter + +... +# using '%' as delimiter +modparam("cfgt", "callid_prefix", "TEST-ID%") +... + + +
+ +
+ + +
From 1b5766548dd637615b2284c5363d5bdf123a8573 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Tue, 15 Dec 2015 11:22:10 +0100 Subject: [PATCH 030/142] debugger: add cfgt support --- modules/debugger/debugger_api.c | 19 +++++++++++++++++++ modules/debugger/debugger_mod.c | 21 +++++++++++++++++++++ modules/debugger/doc/debugger_admin.xml | 22 ++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/modules/debugger/debugger_api.c b/modules/debugger/debugger_api.c index b1e7fe1aa4a..107fa09b4f6 100644 --- a/modules/debugger/debugger_api.c +++ b/modules/debugger/debugger_api.c @@ -26,6 +26,7 @@ #include #include +#include "../cfgt/cfgt.h" #include "../../dprint.h" #include "../../events.h" #include "../../locking.h" @@ -70,6 +71,7 @@ str *dbg_get_state_name(int t) #define DBG_CFGTRACE_ON (1<<0) #define DBG_ABKPOINT_ON (1<<1) #define DBG_LBKPOINT_ON (1<<2) +#define DBG_CFGTEST_ON (1<<3) static str _dbg_status_list[] = { str_init("cfgtrace-on"), @@ -78,6 +80,8 @@ static str _dbg_status_list[] = { str_init("abkpoint-off"), str_init("lbkpoint-on"), str_init("lbkpoint-off"), + str_init("cfgtest-on"), + str_init("cfgtest-off"), {0, 0} }; @@ -89,6 +93,8 @@ str *dbg_get_status_name(int t) return &_dbg_status_list[2]; if(t&DBG_LBKPOINT_ON) return &_dbg_status_list[4]; + if(t&DBG_CFGTEST_ON) + return &_dbg_status_list[6]; return &_dbg_state_list[0]; } @@ -188,6 +194,12 @@ int _dbg_step_loops = 200; */ int _dbg_reset_msgid = 0; +/** + * disabled by default + */ +int _dbg_cfgtest = 0; +cfgt_api_t _dbg_cfgt; + /** * */ @@ -356,6 +368,11 @@ int dbg_cfg_trace(void *data) ); } } + if(_dbg_pid_list[process_no].set&DBG_CFGTEST_ON) + { + if(_dbg_cfgt.cfgt_process_route(msg, a)<0) + LM_ERR("Error processing route\n"); + } if(!(_dbg_pid_list[process_no].set&DBG_ABKPOINT_ON)) { /* no breakpoints to be considered */ @@ -590,6 +607,8 @@ int dbg_init_mypid(void) _dbg_pid_list[process_no].set |= DBG_ABKPOINT_ON; if(_dbg_cfgtrace==1) _dbg_pid_list[process_no].set |= DBG_CFGTRACE_ON; + if(_dbg_cfgtest==1) + _dbg_pid_list[process_no].set |= DBG_CFGTEST_ON; if(_dbg_reset_msgid==1) { LM_DBG("[%d] create locks\n", process_no); diff --git a/modules/debugger/debugger_mod.c b/modules/debugger/debugger_mod.c index d0a35aff82f..44c58650940 100644 --- a/modules/debugger/debugger_mod.c +++ b/modules/debugger/debugger_mod.c @@ -27,6 +27,7 @@ #include #include +#include "../cfgt/cfgt.h" #include "../../sr_module.h" #include "../../dprint.h" #include "../../ut.h" @@ -71,6 +72,10 @@ extern char *_dbg_cfgtrace_lname; extern int _dbg_step_usleep; extern int _dbg_step_loops; extern int _dbg_reset_msgid; +extern int _dbg_cfgtest; + +/* cfgt api */ +extern cfgt_api_t _dbg_cfgt; static int _dbg_sip_msg_cline; static char * _dbg_cfgtrace_facility_str = 0; @@ -111,6 +116,7 @@ static param_export_t params[]={ {"mod_facility", PARAM_STRING|USE_FUNC_PARAM, (void*)dbg_mod_facility_param}, {"reset_msgid", INT_PARAM, &_dbg_reset_msgid}, {"cfgpkgcheck", INT_PARAM, &_dbg_cfgpkgcheck}, + {"cfgtest", INT_PARAM, &_dbg_cfgtest}, {0, 0, 0} }; @@ -136,6 +142,8 @@ struct module_exports exports = { static int mod_init(void) { int fl; + bind_cfgt_t bind_cfgt; + if (_dbg_cfgtrace_facility_str!=NULL) { fl = str2facility(_dbg_cfgtrace_facility_str); @@ -187,6 +195,19 @@ static int mod_init(void) return -1; } } + if(_dbg_cfgtest==1) + { + bind_cfgt = (bind_cfgt_t)find_export("cfgt_bind_cfgt", 1, 0); + if (!bind_cfgt) { + LM_ERR("can't find cfgt module\n"); + return -1; + } + + if (bind_cfgt(&_dbg_cfgt) < 0) { + return -1; + } + LM_INFO("bind to cfgt module\n"); + } return dbg_init_bp_list(); } diff --git a/modules/debugger/doc/debugger_admin.xml b/modules/debugger/doc/debugger_admin.xml index f003fb5f80f..cddfc26746f 100644 --- a/modules/debugger/doc/debugger_admin.xml +++ b/modules/debugger/doc/debugger_admin.xml @@ -418,6 +418,28 @@ modparam("debugger", "reset_msgid", 1)
+
+ <varname>cfgtest</varname> (int) + + Control whether the cfgt module is enabled or disabled + at startup. Module cfgt needs to be loaded before. + + + + Default value is 0 (disabled). + + + + Set <varname>cfgtest</varname> parameter + +... +loadmodule "cfgt.so" +modparam("debugger", "cfgtest", 1) +... + + +
+
From ef5ba34baa4f5a54ab634dc7e06e0de1daf45dd2 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Tue, 15 Dec 2015 11:42:58 +0100 Subject: [PATCH 031/142] debugger: refresh README --- modules/debugger/README | 45 ++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/modules/debugger/README b/modules/debugger/README index 609bc3ca57c..7ef1ef1c349 100644 --- a/modules/debugger/README +++ b/modules/debugger/README @@ -41,6 +41,7 @@ Daniel-Constantin Mierla 3.14. log_assign (int) 3.15. cfgpkgcheck (int) 3.16. reset_msgid (int) + 3.17. cfgtest (int) 4. Functions @@ -76,9 +77,10 @@ Daniel-Constantin Mierla 1.14. Set log_assign parameter 1.15. Set cfgpkgcheck parameter 1.16. Set reset_msgid parameter - 1.17. dbg_breakpoint usage - 1.18. dbg_pv_dump usage - 1.19. dbg_sip_msg usage + 1.17. Set cfgtest parameter + 1.18. dbg_breakpoint usage + 1.19. dbg_pv_dump usage + 1.20. dbg_sip_msg usage Chapter 1. Admin Guide @@ -108,6 +110,7 @@ Chapter 1. Admin Guide 3.14. log_assign (int) 3.15. cfgpkgcheck (int) 3.16. reset_msgid (int) + 3.17. cfgtest (int) 4. Functions @@ -183,6 +186,7 @@ Chapter 1. Admin Guide 3.14. log_assign (int) 3.15. cfgpkgcheck (int) 3.16. reset_msgid (int) + 3.17. cfgtest (int) 3.1. cfgtrace (int) @@ -389,13 +393,26 @@ modparam("debugger", "cfgpkgcheck", 1) modparam("debugger", "reset_msgid", 1) ... +3.17. cfgtest (int) + + Control whether the cfgt module is enabled or disabled at startup. + Module cfgt needs to be loaded before. + + Default value is "0" (disabled). + + Example 1.17. Set cfgtest parameter +... +loadmodule "cfgt.so" +modparam("debugger", "cfgtest", 1) +... + 4. Functions 4.1. dbg_breakpoint(mode) 4.2. dbg_pv_dump([mask] [, level]) 4.3. dbg_sip_msg([log_level], [facility]) -4.1. dbg_breakpoint(mode) +4.1. dbg_breakpoint(mode) Anchor a breakpoint at the current line of the config (the one on which this function is called). The 'mode' specifies whether the breakpoint @@ -404,13 +421,13 @@ modparam("debugger", "reset_msgid", 1) Note that this version of the module does not export this anchors to RPC for interactive debugging (temporarily disabled). - Example 1.17. dbg_breakpoint usage + Example 1.18. dbg_breakpoint usage ... if($si=="10.0.0.10") dbg_breakpoint("1"); ... -4.2. dbg_pv_dump([mask] [, level]) +4.2. dbg_pv_dump([mask] [, level]) Prints the content of pv_cache on json format. Defaults are mask=31 and level = "L_DBG" @@ -432,7 +449,7 @@ if($si=="10.0.0.10") * L_INFO - log level 2 * L_DBG - log level 3 - Example 1.18. dbg_pv_dump usage + Example 1.19. dbg_pv_dump usage ... $var(temp) = 1; $avp(s:more_avp) = 2; @@ -455,7 +472,7 @@ vp(x)":[{"different":["foo"]},{"other":[2,1],"more":["hi","bye"]}],"$T_branch_id x":0,"$var(empty)":0} ... -4.3. dbg_sip_msg([log_level], [facility]) +4.3. dbg_sip_msg([log_level], [facility]) Prints how the sip message would look like if it would be sent out at that point in the config(i.e. if the current lump lists would have been @@ -475,7 +492,7 @@ x":0,"$var(empty)":0} force the lump application using msg_apply_changes() function from textopsx module. - Example 1.19. dbg_sip_msg usage + Example 1.20. dbg_sip_msg usage ... dbg_sip_msg(); dbg_sip_msg("L_ERR"); @@ -512,7 +529,7 @@ P-Hint: My hint 5.4. dbg.mod_level 5.5. dbg.reset_msgid -5.1. dbg.ls +5.1. dbg.ls List Kamailio processes with info related to interactive debugging. @@ -526,7 +543,7 @@ P-Hint: My hint dbg.ls dbg.ls 1234 -5.2. dbg.trace +5.2. dbg.trace Control config script running trace. @@ -543,7 +560,7 @@ P-Hint: My hint dbg.trace off dbg.trace on 1234 -5.3. dbg.bp +5.3. dbg.bp Control breakpoints and config execution. @@ -581,7 +598,7 @@ P-Hint: My hint dbg.bp eval 1234 $fu dbg.bp move 1234 -5.4. dbg.mod_level +5.4. dbg.mod_level Specify module log level. @@ -595,7 +612,7 @@ P-Hint: My hint dbg.mod_level core 3 dbg.mod_level tm 3 -5.5. dbg.reset_msgid +5.5. dbg.reset_msgid Resets the message sequence ($mi). Internally there is no real change. This can be useful for unit test cases in order to be able to replicate From e0f7a0c678b37c44312369dd90ffdc531782bb99 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 15 Dec 2015 12:26:02 +0100 Subject: [PATCH 032/142] websocket: fixed Makefile after previous commit - whitespace required after ifneq --- modules/websocket/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/websocket/Makefile b/modules/websocket/Makefile index 010aa90c973..42c4c79501c 100644 --- a/modules/websocket/Makefile +++ b/modules/websocket/Makefile @@ -13,12 +13,14 @@ SSL_BUILDER=$(shell \ if pkg-config --exists libssl; then \ echo 'pkg-config libssl'; \ fi) -ifneq($(SSL_BUILDER),) + +ifneq ($(SSL_BUILDER),) SSL_BUILDER+=$(shell \ if pkg-config --exists libcrypto; then \ echo 'libcrypto'; \ fi) endif + endif ifneq ($(SSL_BUILDER),) From 09e823deb39940d1601a26504d4431ca74d70453 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Tue, 15 Dec 2015 14:37:57 +0100 Subject: [PATCH 033/142] Makefile.groups: add cfgt module to mod_list_basic --- Makefile.groups | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.groups b/Makefile.groups index c5f5300c796..96b36056bd3 100644 --- a/Makefile.groups +++ b/Makefile.groups @@ -15,7 +15,7 @@ mod_list_basic=async auth benchmark blst cfg_rpc cfgutils corex counters \ nat_traversal nathelper path pike pv ratelimit rr rtimer \ rtpproxy sanity sdpops siputils sl statistics textops \ textopsx tm tmx topoh xlog rtpengine stun sipt tcpops \ - auth_xkeys smsops tsilo + auth_xkeys smsops tsilo cfgt # - extra used modules, with no extra dependency mod_list_extra=avp auth_diameter call_control dmq domainpolicy msrp pdb \ From b8e3aff1079e4a617aa273553a20d664d0c368c2 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 16 Dec 2015 08:20:55 +0100 Subject: [PATCH 034/142] cfgt: fix compile warning for len field comparison --- modules/cfgt/cfgt_int.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cfgt/cfgt_int.c b/modules/cfgt/cfgt_int.c index f5e87dbe944..5bd48ba50d8 100644 --- a/modules/cfgt/cfgt_int.c +++ b/modules/cfgt/cfgt_int.c @@ -236,7 +236,7 @@ cfgt_node_p cfgt_create_node(struct sip_msg *msg) { node->msgid = msg->id; LM_DBG("msgid:%d\n", node->msgid); - if(_cfgt_get_hdr(msg, &node->uuid)!=0 || &node->uuid.len==0) + if(_cfgt_get_hdr(msg, &node->uuid)!=0 || node->uuid.len==0) { LM_ERR("cannot get value of cfgtest uuid header!!\n"); goto error; From 64583809c677384e2fcd54a5ba7f921b3ea59c51 Mon Sep 17 00:00:00 2001 From: smititelu Date: Wed, 16 Dec 2015 13:28:18 +0200 Subject: [PATCH 035/142] debugger: Fix coredump when kamailio stopped Upon kamailio stop, 'dbg_cfg' pointed to invalid memory zone(not NULL). Reset the pointer to NULL upon module_destroy() and do the NULL checks. Reported by foucse in issue #446. --- modules/debugger/debugger_api.c | 8 ++++++++ modules/debugger/debugger_mod.c | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/modules/debugger/debugger_api.c b/modules/debugger/debugger_api.c index 107fa09b4f6..d0ce44fd205 100644 --- a/modules/debugger/debugger_api.c +++ b/modules/debugger/debugger_api.c @@ -1354,6 +1354,10 @@ int dbg_get_mod_debug_level(char *mname, int mnlen, int *mlevel) if(_dbg_mod_table==NULL) return -1; + if (!dbg_cfg) { + return -1; + } + if(cfg_get(dbg, dbg_cfg, mod_level_mode)==0) return -1; @@ -1397,6 +1401,10 @@ int dbg_get_mod_debug_facility(char *mname, int mnlen, int *mfacility) if(_dbg_mod_table==NULL) return -1; + if (!dbg_cfg) { + return -1; + } + if(cfg_get(dbg, dbg_cfg, mod_facility_mode)==0) return -1; diff --git a/modules/debugger/debugger_mod.c b/modules/debugger/debugger_mod.c index 44c58650940..fd1d91bdd28 100644 --- a/modules/debugger/debugger_mod.c +++ b/modules/debugger/debugger_mod.c @@ -167,6 +167,12 @@ static int mod_init(void) LM_ERR("Fail to declare the configuration\n"); return -1; } + + /* anyhow, should fail before */ + if (!dbg_cfg) { + return -1; + } + LM_DBG("cfg level_mode:%d facility_mode:%d hash_size:%d\n", cfg_get(dbg, dbg_cfg, mod_level_mode), cfg_get(dbg, dbg_cfg, mod_facility_mode), @@ -231,6 +237,7 @@ static int child_init(int rank) */ static void mod_destroy(void) { + dbg_cfg = NULL; } /** @@ -352,19 +359,27 @@ static int dbg_mod_level_param(modparam_t type, void *val) } s.s = (char*)val; s.len = p - s.s; + + if (!dbg_cfg) { + return -1; + } + LM_DBG("cfg level_mode:%d hash_size:%d\n", cfg_get(dbg, dbg_cfg, mod_level_mode), cfg_get(dbg, dbg_cfg, mod_hash_size)); + if(dbg_init_mod_levels(cfg_get(dbg, dbg_cfg, mod_hash_size))<0) { LM_ERR("failed to init per module log level\n"); return -1; } + if(dbg_set_mod_debug_level(s.s, s.len, &l)<0) { LM_ERR("cannot store parameter: %s\n", (char*)val); return -1; } + return 0; } @@ -392,19 +407,27 @@ static int dbg_mod_facility_param(modparam_t type, void *val) s.s = (char*)val; s.len = p - s.s; + + if (!dbg_cfg) { + return -1; + } + LM_DBG("cfg facility_mode:%d hash_size:%d\n", cfg_get(dbg, dbg_cfg, mod_facility_mode), cfg_get(dbg, dbg_cfg, mod_hash_size)); + if(dbg_init_mod_levels(cfg_get(dbg, dbg_cfg, mod_hash_size))<0) { LM_ERR("failed to init per module log level\n"); return -1; } + if(dbg_set_mod_debug_facility(s.s, s.len, &fl)<0) { LM_ERR("cannot store parameter: %s\n", (char*)val); return -1; } + return 0; } From 424ac4dba745dd728e225895f9fb40e287ec365f Mon Sep 17 00:00:00 2001 From: Christian Kuehnke Date: Wed, 16 Dec 2015 18:47:36 +0100 Subject: [PATCH 036/142] core: rewrite add_interfaces() with getifaddrs() based implementation To make IPV6 work with Solaris, add_interfaces() had to be modified. I decided to reimplement it with a getifaddrs() based implementation, which is available from Solaris 11 upwards, and also on FreeBSD and Linux. By default, the latter continues to use the netlink based variant. --- Makefile.defs | 2 +- socket_info.c | 142 ++++++++++++-------------------------------------- 2 files changed, 33 insertions(+), 111 deletions(-) diff --git a/Makefile.defs b/Makefile.defs index 2b2078bb257..177f58c631a 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -1785,7 +1785,7 @@ ifeq ($(CC_NAME), suncc) endif OLD_SOLARIS= $(shell echo "$(OSREL)" | \ sed -e 's/^5\.[0-6][^0-9]*$$/yes/' ) - LIBS+= -L$(LOCALBASE)/lib -lxnet -lnsl + LIBS+= -L$(LOCALBASE)/lib -lxnet -lsocket -lnsl ifeq ($(OLD_SOLARIS), yes) LIBS+=-lposix4 else diff --git a/socket_info.c b/socket_info.c index 678b6d85679..e2d914734dc 100644 --- a/socket_info.c +++ b/socket_info.c @@ -41,6 +41,7 @@ #include #include +#include #ifdef HAVE_SYS_SOCKIO_H #include #endif @@ -1129,7 +1130,8 @@ static int build_iface_list(void) return -1; } -/* add all family type addresses of interface if_to the socket_info array +/* add all family type addresses of interface if_name to the socket_info array + * if family ==0, uses all families * if if_name==0, adds all addresses on all interfaces * uses RTNETLINK sockets to get addresses on the present interface on LINUX * return: -1 on error, 0 on success @@ -1160,7 +1162,7 @@ int add_interfaces_via_netlink(char* if_name, int family, unsigned short port, LM_DBG("in add_iface_via_netlink Name %s Address %s\n", ifaces[i].name, tmp->addr); /* match family */ - if (family == tmp->family){ + if (family && family == tmp->family){ /* check if loopback */ if (ifaces[i].flags & IFF_LOOPBACK){ LM_DBG("INTERFACE %s is loopback", ifaces[i].name); @@ -1182,129 +1184,49 @@ int add_interfaces_via_netlink(char* if_name, int family, unsigned short port, #endif /* __OS_linux */ /* add all family type addresses of interface if_name to the socket_info array + * if family ==0, uses all families * if if_name==0, adds all addresses on all interfaces - * WARNING: it only works with ipv6 addresses on FreeBSD * return: -1 on error, 0 on success */ int add_interfaces(char* if_name, int family, unsigned short port, unsigned short proto, struct addr_info** ai_l) { - struct ifconf ifc; - struct ifreq ifr; - struct ifreq ifrcopy; - char* last; - char* p; - int size; - int lastlen; - int s; char* tmp; struct ip_addr addr; - int ret; + int ret = -1; enum si_flags flags; + struct ifaddrs *ifap, *ifa; -#ifdef HAVE_SOCKADDR_SA_LEN - #ifndef MAX - #define MAX(a,b) ( ((a)>(b))?(a):(b)) - #endif -#endif - /* ipv4 or ipv6 only*/ - flags=SI_NONE; - s=socket(family, SOCK_DGRAM, 0); - ret=-1; - lastlen=0; - ifc.ifc_req=0; - for (size=100; ; size*=2){ - ifc.ifc_len=size*sizeof(struct ifreq); - ifc.ifc_req=(struct ifreq*) pkg_malloc(size*sizeof(struct ifreq)); - if (ifc.ifc_req==0){ - LM_ERR("memory allocation failure\n"); - goto error; - } - if (ioctl(s, SIOCGIFCONF, &ifc)==-1){ - if(errno==EBADF) return 0; /* invalid descriptor => no such ifs*/ - LM_ERR("ioctl failed: %s\n", strerror(errno)); - goto error; - } - if ((lastlen) && (ifc.ifc_len==lastlen)) break; /*success, - len not changed*/ - lastlen=ifc.ifc_len; - /* try a bigger array*/ - pkg_free(ifc.ifc_req); - } - - last=(char*)ifc.ifc_req+ifc.ifc_len; - for(p=(char*)ifc.ifc_req; pifa_next) { - /* copy contents into ifr structure - * warning: it might be longer (e.g. ipv6 address) */ - memcpy(&ifr, p, sizeof(ifr)); - if (ifr.ifr_addr.sa_family!=family){ - /*printf("strange family %d skipping...\n", - ifr->ifr_addr.sa_family);*/ + if (if_name && strcmp(if_name, ifa->ifa_name)) continue; + if (family && family != ifa->ifa_addr->sa_family) + continue; + sockaddr2ip_addr(&addr, (struct sockaddr*)ifa->ifa_addr); + tmp=ip_addr2a(&addr); + if (ifa->ifa_flags & IFF_LOOPBACK) + flags = SI_IS_LO; + else + flags = SI_NONE; + if (new_addr_info2list(tmp, flags, ai_l)!=0) + { + LM_ERR("new_addr_info2list failed\n"); + ret = -1; + break; } - - /*get flags*/ - ifrcopy=ifr; - if (ioctl(s, SIOCGIFFLAGS, &ifrcopy)!=-1){ /* ignore errors */ - /* ignore down ifs only if listening on all of them*/ - if (if_name==0){ - /* if if not up, skip it*/ - if (!(ifrcopy.ifr_flags & IFF_UP)) continue; - } - } - - - - if ((if_name==0)|| - (strncmp(if_name, ifr.ifr_name, sizeof(ifr.ifr_name))==0)){ - - /*add address*/ - sockaddr2ip_addr(&addr, - (struct sockaddr*)(p+(long)&((struct ifreq*)0)->ifr_addr)); - if ((tmp=ip_addr2a(&addr))==0) goto error; - /* check if loopback */ - if (ifrcopy.ifr_flags & IFF_LOOPBACK) - flags|=SI_IS_LO; - /* save the info */ - if (new_addr_info2list(tmp, flags, ai_l)!=0){ - LM_ERR("new_addr_info2list failed\n"); - goto error; - } - ret=0; - } - /* - printf("%s:\n", ifr->ifr_name); - printf(" "); - print_sockaddr(&(ifr->ifr_addr)); - printf(" "); - ls_ifflags(ifr->ifr_name, family, options); - printf("\n");*/ + LM_DBG("If: %8s Fam: %8x Flg: %16lx Adr: %s\n", ifa->ifa_name, ifa->ifa_addr->sa_family, ifa->ifa_flags, tmp); + + ret = 0; } - pkg_free(ifc.ifc_req); /*clean up*/ - close(s); + freeifaddrs(ifap); return ret; -error: - if (ifc.ifc_req) pkg_free(ifc.ifc_req); - close(s); - return -1; } @@ -1474,7 +1396,7 @@ static int fix_socket_list(struct socket_info **list, int* type_flags) for (si=*list;si;){ next=si->next; ai_lst=0; - if (add_interfaces(si->name.s, AF_INET, si->port_no, + if (add_interfaces(si->name.s, 0, si->port_no, si->proto, &ai_lst)!=-1){ if (si->flags & SI_IS_MHOMED){ if((new_si=new_sock2list_after(ai_lst->name.s, 0, si->port_no, From 1682896e2971508e454448d2a89ba5ab10811a84 Mon Sep 17 00:00:00 2001 From: Luis Azedo Date: Wed, 16 Dec 2015 20:50:41 +0000 Subject: [PATCH 037/142] presence : fix notify version when subs_node <> 3 when submode <> 3 the notify version is always the same (first watcher) for all watchers --- modules/presence/notify.c | 8 +++++++- modules/presence_dialoginfo/add_events.c | 1 + modules/presence_dialoginfo/notify_body.c | 25 +++++++++++++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/modules/presence/notify.c b/modules/presence/notify.c index 6466fc1a2e1..efb8a489fc9 100644 --- a/modules/presence/notify.c +++ b/modules/presence/notify.c @@ -1470,6 +1470,7 @@ int send_notify_request(subs_t* subs, subs_t * watcher_subs, c_back_param *cb_param= NULL; str* final_body= NULL; uac_req_t uac_r; + str* aux_body = NULL; LM_DBG("dialog info:\n"); printf_subs(subs); @@ -1532,7 +1533,12 @@ int send_notify_request(subs_t* subs, subs_t * watcher_subs, /* call aux_body_processing if exists */ if(subs->event->aux_body_processing) { - subs->event->aux_body_processing(subs, notify_body); + aux_body = subs->event->aux_body_processing(subs, notify_body); + if(aux_body) { + xmlFree(notify_body->s); + pkg_free(notify_body); + notify_body = aux_body; + } } /* apply authorization rules if exists */ diff --git a/modules/presence_dialoginfo/add_events.c b/modules/presence_dialoginfo/add_events.c index fe1e4168a08..8382fc7847d 100644 --- a/modules/presence_dialoginfo/add_events.c +++ b/modules/presence_dialoginfo/add_events.c @@ -57,6 +57,7 @@ int dlginfo_add_events(void) /* modify XML body for each watcher to set the correct "version" */ event.aux_body_processing = dlginfo_body_setversion; + event.aux_free_body = free_xml_body; if (pres_add_event(&event) < 0) { diff --git a/modules/presence_dialoginfo/notify_body.c b/modules/presence_dialoginfo/notify_body.c index 5db2a9853ec..9ad377cd916 100644 --- a/modules/presence_dialoginfo/notify_body.c +++ b/modules/presence_dialoginfo/notify_body.c @@ -538,6 +538,7 @@ str *dlginfo_body_setversion(subs_t *subs, str *body) { char *version_start=0; char version[MAX_INT_LEN + 2]; /* +2 becasue of trailing " and \0 */ int version_len; + str* aux_body = NULL; if (!body) { return NULL; @@ -564,9 +565,29 @@ str *dlginfo_body_setversion(subs_t *subs, str *body) { version_len = snprintf(version, MAX_INT_LEN + 2,"%d\"", subs->version); if (version_len >= MAX_INT_LEN + 2) { LM_ERR("failed to convert 'version' to string\n"); - memcpy(version_start, "00000000000\"", 12); return NULL; } + + aux_body= (str*)pkg_malloc(sizeof(str)); + if(aux_body== NULL) + { + ERR_MEM(PKG_MEM_STR); + return NULL; + } + memset(aux_body, 0, sizeof(str)); + aux_body->s= (char*)pkg_malloc( body->len * sizeof(char)); + if(aux_body->s== NULL) + { + pkg_free(aux_body); + ERR_MEM(PKG_MEM_STR); + return NULL; + } + memcpy(aux_body->s, body->s, body->len); + aux_body->len= body->len; + + /* again but on the copied str, no checks needed */ + version_start = strstr(aux_body->s + 34, "version="); + version_start += 9; /* Replace the placeholder 00000000000 with the version. * Put the padding behind the "" */ @@ -574,5 +595,5 @@ str *dlginfo_body_setversion(subs_t *subs, str *body) { memcpy(version_start, version, version_len); memset(version_start + version_len, ' ', 12 - version_len); - return NULL; + return aux_body; } From e1c9e07fc129569143063f38fec34f5a01151e26 Mon Sep 17 00:00:00 2001 From: Giacomo Vacca Date: Thu, 17 Dec 2015 09:38:32 +0000 Subject: [PATCH 038/142] cfgt: improved documentation - Provide an example of Call-ID to identify a scenario --- modules/cfgt/doc/cfgt_admin.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/cfgt/doc/cfgt_admin.xml b/modules/cfgt/doc/cfgt_admin.xml index 07b8ea4f66f..e507456e0d3 100644 --- a/modules/cfgt/doc/cfgt_admin.xml +++ b/modules/cfgt/doc/cfgt_admin.xml @@ -23,7 +23,7 @@ In order to identify defferent scenarios a prefix string should be - used at Call-ID header. + used inside the Call-ID header.
@@ -62,7 +62,7 @@ <varname>basedir</varname> (string) Control where the config reports should be stored. The dir must - exists and &kamailioname; must have perms to write on it. + exist and &kamailioname; must have permissions to write on it. @@ -126,7 +126,9 @@ modparam("cfgt", "mask", 12) <varname>callid_prefix</varname> (string) Prefix used to indentify test scenario messages. Last char of the - string will be used as delimiter. + string will be used as delimiter for the scenario ID. With parameter + set to NGCP% and Call-ID NGCP%123%456 + the scenario identified will be 123. From c131323e77b4cf39b0121aa6e59c0b67174b8679 Mon Sep 17 00:00:00 2001 From: Giacomo Vacca Date: Thu, 17 Dec 2015 09:38:43 +0000 Subject: [PATCH 039/142] cfgt: update README - Provide an example of Call-ID to identify a scenario --- modules/cfgt/README | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/modules/cfgt/README b/modules/cfgt/README index a3be5ffac22..3e2b606ff09 100644 --- a/modules/cfgt/README +++ b/modules/cfgt/README @@ -10,7 +10,7 @@ Victor Seva - Copyright © 2015 Victor Seva (sipwise.com) + Copyright © 2015 Victor Seva (sipwise.com) __________________________________________________________________ Table of Contents @@ -58,7 +58,7 @@ Chapter 1. Admin Guide SIP scenarios. In order to identify defferent scenarios a prefix string should be used - at Call-ID header. + inside the Call-ID header. 2. Dependencies @@ -84,10 +84,10 @@ Chapter 1. Admin Guide 3.1. basedir (string) - Control where the config reports should be stored. The dir must exists - and Kamailio SIP Server Platform must have perms to write on it. + Control where the config reports should be stored. The dir must exist + and Kamailio SIP Server Platform must have permissions to write on it. - Default value is "/tmp". + Default value is “/tmpâ€. Example 1.1. Set cfgtrace parameter ... @@ -104,7 +104,7 @@ modparam("cfgt", "basedir", "/var/run/kamailio/cfgtest") * 16 - dump DP_OTHER vars * 32 - dump ALL vars - Default value is "32" (ALL). + Default value is “32†(ALL). Example 1.2. Set mask parameter ... @@ -115,9 +115,11 @@ modparam("cfgt", "mask", 12) 3.3. callid_prefix (string) Prefix used to indentify test scenario messages. Last char of the - string will be used as delimiter. + string will be used as delimiter for the scenario ID. With parameter + set to “NGCP%†and Call-ID “NGCP%123%456†the scenario identified will + be “123â€. - Default value is "NGCP%" (using "%" as delimiter). + Default value is “NGCP%†(using “%†as delimiter). Example 1.3. Set callid_prefix parameter ... From 31933ccc40f9af36caa9f0a45e0a57aebe0b91d4 Mon Sep 17 00:00:00 2001 From: Giacomo Vacca Date: Thu, 17 Dec 2015 16:43:53 +0000 Subject: [PATCH 040/142] cfgt: fixed a few typos in documentation --- modules/cfgt/doc/cfgt_admin.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/cfgt/doc/cfgt_admin.xml b/modules/cfgt/doc/cfgt_admin.xml index e507456e0d3..4282d7d3a41 100644 --- a/modules/cfgt/doc/cfgt_admin.xml +++ b/modules/cfgt/doc/cfgt_admin.xml @@ -22,7 +22,7 @@ SIP scenarios. - In order to identify defferent scenarios a prefix string should be + In order to identify different scenarios a prefix string should be used inside the Call-ID header.
@@ -125,7 +125,7 @@ modparam("cfgt", "mask", 12)
<varname>callid_prefix</varname> (string) - Prefix used to indentify test scenario messages. Last char of the + Prefix used to identify test scenario messages. Last char of the string will be used as delimiter for the scenario ID. With parameter set to NGCP% and Call-ID NGCP%123%456 the scenario identified will be 123. From 806e0fa1f970062bee25d95e33058363735c3bba Mon Sep 17 00:00:00 2001 From: Giacomo Vacca Date: Thu, 17 Dec 2015 17:03:18 +0000 Subject: [PATCH 041/142] cfgt: extended documentation - Add a Usage part with .cfg example --- modules/cfgt/doc/cfgt_admin.xml | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/modules/cfgt/doc/cfgt_admin.xml b/modules/cfgt/doc/cfgt_admin.xml index 4282d7d3a41..510b6360628 100644 --- a/modules/cfgt/doc/cfgt_admin.xml +++ b/modules/cfgt/doc/cfgt_admin.xml @@ -148,13 +148,31 @@ modparam("cfgt", "callid_prefix", "TEST-ID%")
- - + + Example of configuration: + + +... +#!ifdef WITH_DEBUG +# ----- cfgt params ----- +modparam("cfgt", "basedir", "/tmp/kamailio/cfgtest") +modparam("cfgt", "callid_prefix", "TRACE-ID%") +modparam("cfgt", "mask", 32) + +# ----- debugger params ----- +modparam("debugger", "cfgtrace", 1) +modparam("debugger", "log_level_name", "exec") + +modparam("debugger", "cfgtest", 1) +#!endif +... + + From 08a8a8eee5d66c017defbbe749ce28cfd2984d92 Mon Sep 17 00:00:00 2001 From: Giacomo Vacca Date: Thu, 17 Dec 2015 17:03:58 +0000 Subject: [PATCH 042/142] cfgt: recompiled README --- modules/cfgt/README | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/modules/cfgt/README b/modules/cfgt/README index 3e2b606ff09..dca039d7d2d 100644 --- a/modules/cfgt/README +++ b/modules/cfgt/README @@ -29,6 +29,8 @@ Victor Seva 3.2. mask (int) 3.3. callid_prefix (string) + 4. Usage + List of Examples 1.1. Set cfgtrace parameter @@ -51,13 +53,15 @@ Chapter 1. Admin Guide 3.2. mask (int) 3.3. callid_prefix (string) + 4. Usage + 1. Overview This module provides a report of the way Kamailio SIP Server Platform configuration has been executed as part of a unit test for different SIP scenarios. - In order to identify defferent scenarios a prefix string should be used + In order to identify different scenarios a prefix string should be used inside the Call-ID header. 2. Dependencies @@ -114,10 +118,10 @@ modparam("cfgt", "mask", 12) 3.3. callid_prefix (string) - Prefix used to indentify test scenario messages. Last char of the - string will be used as delimiter for the scenario ID. With parameter - set to “NGCP%†and Call-ID “NGCP%123%456†the scenario identified will - be “123â€. + Prefix used to identify test scenario messages. Last char of the string + will be used as delimiter for the scenario ID. With parameter set to + “NGCP%†and Call-ID “NGCP%123%456†the scenario identified will be + “123â€. Default value is “NGCP%†(using “%†as delimiter). @@ -126,3 +130,25 @@ modparam("cfgt", "mask", 12) # using '%' as delimiter modparam("cfgt", "callid_prefix", "TEST-ID%") ... + +4. Usage + + This module is used by the debugger module, so it must be loaded first. + To enable the generation of the reports, the debugger module must be + configured by setting the cfgtest parameter to "1". + + Example of configuration: +... +#!ifdef WITH_DEBUG +# ----- cfgt params ----- +modparam("cfgt", "basedir", "/tmp/kamailio/cfgtest") +modparam("cfgt", "callid_prefix", "TRACE-ID%") +modparam("cfgt", "mask", 32) + +# ----- debugger params ----- +modparam("debugger", "cfgtrace", 1) +modparam("debugger", "log_level_name", "exec") + +modparam("debugger", "cfgtest", 1) +#!endif +... From 412f155ede8587c1d439503cd7d0e783bc3c0d6b Mon Sep 17 00:00:00 2001 From: lazedo Date: Thu, 17 Dec 2015 18:54:45 +0000 Subject: [PATCH 043/142] presence_dialog : fix compilation --- modules/presence_dialoginfo/notify_body.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/presence_dialoginfo/notify_body.c b/modules/presence_dialoginfo/notify_body.c index 9ad377cd916..e6dc05078e2 100644 --- a/modules/presence_dialoginfo/notify_body.c +++ b/modules/presence_dialoginfo/notify_body.c @@ -571,7 +571,7 @@ str *dlginfo_body_setversion(subs_t *subs, str *body) { aux_body= (str*)pkg_malloc(sizeof(str)); if(aux_body== NULL) { - ERR_MEM(PKG_MEM_STR); + LM_ERR("error allocating memory for aux body str\n"); return NULL; } memset(aux_body, 0, sizeof(str)); @@ -579,7 +579,7 @@ str *dlginfo_body_setversion(subs_t *subs, str *body) { if(aux_body->s== NULL) { pkg_free(aux_body); - ERR_MEM(PKG_MEM_STR); + LM_ERR("error allocating memory for aux body buffer\n"); return NULL; } memcpy(aux_body->s, body->s, body->len); From b6b7de8832e4ab22ef2c00ebb2c1e1b6ced9ff35 Mon Sep 17 00:00:00 2001 From: Luis Azedo Date: Thu, 17 Dec 2015 21:02:43 +0000 Subject: [PATCH 044/142] presence_dialoginfo : aux_body should return xmldoc instead of char --- modules/presence/notify.c | 3 +-- modules/presence_dialoginfo/notify_body.c | 13 +++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/modules/presence/notify.c b/modules/presence/notify.c index efb8a489fc9..f6a0ba9548e 100644 --- a/modules/presence/notify.c +++ b/modules/presence/notify.c @@ -1535,8 +1535,7 @@ int send_notify_request(subs_t* subs, subs_t * watcher_subs, { aux_body = subs->event->aux_body_processing(subs, notify_body); if(aux_body) { - xmlFree(notify_body->s); - pkg_free(notify_body); + free_notify_body(notify_body, subs->event); notify_body = aux_body; } } diff --git a/modules/presence_dialoginfo/notify_body.c b/modules/presence_dialoginfo/notify_body.c index e6dc05078e2..710fe918235 100644 --- a/modules/presence_dialoginfo/notify_body.c +++ b/modules/presence_dialoginfo/notify_body.c @@ -595,5 +595,18 @@ str *dlginfo_body_setversion(subs_t *subs, str *body) { memcpy(version_start, version, version_len); memset(version_start + version_len, ' ', 12 - version_len); + xmlDocPtr doc = xmlReadMemory(aux_body->s, aux_body->len, "noname.xml", NULL, 0); + if (doc == NULL) { + LM_ERR("error allocation xmldoc\n"); + pkg_free(aux_body->s); + pkg_free(aux_body); + return NULL; + } + pkg_free(aux_body->s); + xmlDocDumpFormatMemory(doc,(xmlChar**)(void*)&aux_body->s, &aux_body->len, 1); + + xmlCleanupParser(); + xmlMemoryDump(); + return aux_body; } From 2b96041540d7b9bf050dbacb78b71085bbc7c03f Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Thu, 17 Dec 2015 23:29:32 +0100 Subject: [PATCH 045/142] Makefile.defs: version set to 4.4.0-dev8 --- Makefile.defs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.defs b/Makefile.defs index 2b2078bb257..2e9f0817a3f 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -97,7 +97,7 @@ INSTALL_FLAVOUR=$(FLAVOUR) VERSION = 4 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -dev7 +EXTRAVERSION = -dev8 # memory manager switcher # 0 - f_malloc (fast malloc) From a8cbef5bf5c36e76b3ba1d43e71210c5b0519b24 Mon Sep 17 00:00:00 2001 From: Giacomo Vacca Date: Fri, 18 Dec 2015 08:24:58 +0000 Subject: [PATCH 046/142] cfgt: documentation update - Add loadmodule example to highlight ordering requirement --- modules/cfgt/doc/cfgt_admin.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/cfgt/doc/cfgt_admin.xml b/modules/cfgt/doc/cfgt_admin.xml index 510b6360628..39d45e2a7d2 100644 --- a/modules/cfgt/doc/cfgt_admin.xml +++ b/modules/cfgt/doc/cfgt_admin.xml @@ -161,6 +161,11 @@ modparam("cfgt", "callid_prefix", "TEST-ID%") ... #!ifdef WITH_DEBUG +loadmodule "cfgt.so" +loadmodule "debugger.so" +#!endif +... +#!ifdef WITH_DEBUG # ----- cfgt params ----- modparam("cfgt", "basedir", "/tmp/kamailio/cfgtest") modparam("cfgt", "callid_prefix", "TRACE-ID%") From 41975bd9d757a395c6b6e330a8ad243aefde4c4e Mon Sep 17 00:00:00 2001 From: Giacomo Vacca Date: Fri, 18 Dec 2015 08:25:12 +0000 Subject: [PATCH 047/142] cfgt: recompiled README --- modules/cfgt/README | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/cfgt/README b/modules/cfgt/README index dca039d7d2d..d65d5606d68 100644 --- a/modules/cfgt/README +++ b/modules/cfgt/README @@ -140,6 +140,11 @@ modparam("cfgt", "callid_prefix", "TEST-ID%") Example of configuration: ... #!ifdef WITH_DEBUG +loadmodule "cfgt.so" +loadmodule "debugger.so" +#!endif +... +#!ifdef WITH_DEBUG # ----- cfgt params ----- modparam("cfgt", "basedir", "/tmp/kamailio/cfgtest") modparam("cfgt", "callid_prefix", "TRACE-ID%") From 47172912dfb0c22a4d10055505d11b7187d1af35 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Fri, 18 Dec 2015 11:44:09 +0100 Subject: [PATCH 048/142] pkg/kamailio/deb: update version to 4.4.0~dev8 --- pkg/kamailio/deb/debian/changelog | 6 ++++++ pkg/kamailio/deb/jessie/changelog | 6 ++++++ pkg/kamailio/deb/jessie/kamailio.service | 2 +- pkg/kamailio/deb/precise/changelog | 6 ++++++ pkg/kamailio/deb/sid/changelog | 6 ++++++ pkg/kamailio/deb/sid/kamailio.service | 2 +- pkg/kamailio/deb/squeeze/changelog | 6 ++++++ pkg/kamailio/deb/stretch/changelog | 6 ++++++ pkg/kamailio/deb/stretch/kamailio.service | 2 +- pkg/kamailio/deb/trusty/changelog | 6 ++++++ pkg/kamailio/deb/wheezy/changelog | 6 ++++++ 11 files changed, 51 insertions(+), 3 deletions(-) diff --git a/pkg/kamailio/deb/debian/changelog b/pkg/kamailio/deb/debian/changelog index 02bc74cbf50..20724b8d764 100644 --- a/pkg/kamailio/deb/debian/changelog +++ b/pkg/kamailio/deb/debian/changelog @@ -1,3 +1,9 @@ +kamailio (4.4.0~dev8) unstable; urgency=medium + + * update version to 4.4.0~dev8 + + -- Victor Seva Fri, 18 Dec 2015 11:42:59 +0100 + kamailio (4.4.0~dev6) unstable; urgency=medium * update version to 4.4.0~dev6 diff --git a/pkg/kamailio/deb/jessie/changelog b/pkg/kamailio/deb/jessie/changelog index 02bc74cbf50..20724b8d764 100644 --- a/pkg/kamailio/deb/jessie/changelog +++ b/pkg/kamailio/deb/jessie/changelog @@ -1,3 +1,9 @@ +kamailio (4.4.0~dev8) unstable; urgency=medium + + * update version to 4.4.0~dev8 + + -- Victor Seva Fri, 18 Dec 2015 11:42:59 +0100 + kamailio (4.4.0~dev6) unstable; urgency=medium * update version to 4.4.0~dev6 diff --git a/pkg/kamailio/deb/jessie/kamailio.service b/pkg/kamailio/deb/jessie/kamailio.service index f049b39b914..06c3334bd78 100644 --- a/pkg/kamailio/deb/jessie/kamailio.service +++ b/pkg/kamailio/deb/jessie/kamailio.service @@ -1,6 +1,6 @@ [Unit] Description=Kamailio (OpenSER) - the Open Source SIP Server -After=syslog.target network.target +After=network.target [Service] Type=forking diff --git a/pkg/kamailio/deb/precise/changelog b/pkg/kamailio/deb/precise/changelog index 02bc74cbf50..20724b8d764 100644 --- a/pkg/kamailio/deb/precise/changelog +++ b/pkg/kamailio/deb/precise/changelog @@ -1,3 +1,9 @@ +kamailio (4.4.0~dev8) unstable; urgency=medium + + * update version to 4.4.0~dev8 + + -- Victor Seva Fri, 18 Dec 2015 11:42:59 +0100 + kamailio (4.4.0~dev6) unstable; urgency=medium * update version to 4.4.0~dev6 diff --git a/pkg/kamailio/deb/sid/changelog b/pkg/kamailio/deb/sid/changelog index 02bc74cbf50..20724b8d764 100644 --- a/pkg/kamailio/deb/sid/changelog +++ b/pkg/kamailio/deb/sid/changelog @@ -1,3 +1,9 @@ +kamailio (4.4.0~dev8) unstable; urgency=medium + + * update version to 4.4.0~dev8 + + -- Victor Seva Fri, 18 Dec 2015 11:42:59 +0100 + kamailio (4.4.0~dev6) unstable; urgency=medium * update version to 4.4.0~dev6 diff --git a/pkg/kamailio/deb/sid/kamailio.service b/pkg/kamailio/deb/sid/kamailio.service index f049b39b914..06c3334bd78 100644 --- a/pkg/kamailio/deb/sid/kamailio.service +++ b/pkg/kamailio/deb/sid/kamailio.service @@ -1,6 +1,6 @@ [Unit] Description=Kamailio (OpenSER) - the Open Source SIP Server -After=syslog.target network.target +After=network.target [Service] Type=forking diff --git a/pkg/kamailio/deb/squeeze/changelog b/pkg/kamailio/deb/squeeze/changelog index 02bc74cbf50..20724b8d764 100644 --- a/pkg/kamailio/deb/squeeze/changelog +++ b/pkg/kamailio/deb/squeeze/changelog @@ -1,3 +1,9 @@ +kamailio (4.4.0~dev8) unstable; urgency=medium + + * update version to 4.4.0~dev8 + + -- Victor Seva Fri, 18 Dec 2015 11:42:59 +0100 + kamailio (4.4.0~dev6) unstable; urgency=medium * update version to 4.4.0~dev6 diff --git a/pkg/kamailio/deb/stretch/changelog b/pkg/kamailio/deb/stretch/changelog index 02bc74cbf50..20724b8d764 100644 --- a/pkg/kamailio/deb/stretch/changelog +++ b/pkg/kamailio/deb/stretch/changelog @@ -1,3 +1,9 @@ +kamailio (4.4.0~dev8) unstable; urgency=medium + + * update version to 4.4.0~dev8 + + -- Victor Seva Fri, 18 Dec 2015 11:42:59 +0100 + kamailio (4.4.0~dev6) unstable; urgency=medium * update version to 4.4.0~dev6 diff --git a/pkg/kamailio/deb/stretch/kamailio.service b/pkg/kamailio/deb/stretch/kamailio.service index f049b39b914..06c3334bd78 100644 --- a/pkg/kamailio/deb/stretch/kamailio.service +++ b/pkg/kamailio/deb/stretch/kamailio.service @@ -1,6 +1,6 @@ [Unit] Description=Kamailio (OpenSER) - the Open Source SIP Server -After=syslog.target network.target +After=network.target [Service] Type=forking diff --git a/pkg/kamailio/deb/trusty/changelog b/pkg/kamailio/deb/trusty/changelog index 02bc74cbf50..20724b8d764 100644 --- a/pkg/kamailio/deb/trusty/changelog +++ b/pkg/kamailio/deb/trusty/changelog @@ -1,3 +1,9 @@ +kamailio (4.4.0~dev8) unstable; urgency=medium + + * update version to 4.4.0~dev8 + + -- Victor Seva Fri, 18 Dec 2015 11:42:59 +0100 + kamailio (4.4.0~dev6) unstable; urgency=medium * update version to 4.4.0~dev6 diff --git a/pkg/kamailio/deb/wheezy/changelog b/pkg/kamailio/deb/wheezy/changelog index 02bc74cbf50..20724b8d764 100644 --- a/pkg/kamailio/deb/wheezy/changelog +++ b/pkg/kamailio/deb/wheezy/changelog @@ -1,3 +1,9 @@ +kamailio (4.4.0~dev8) unstable; urgency=medium + + * update version to 4.4.0~dev8 + + -- Victor Seva Fri, 18 Dec 2015 11:42:59 +0100 + kamailio (4.4.0~dev6) unstable; urgency=medium * update version to 4.4.0~dev6 From b7acbe4d676cc68f790f12f29186dfab31301074 Mon Sep 17 00:00:00 2001 From: lazedo Date: Fri, 18 Dec 2015 14:40:18 +0000 Subject: [PATCH 049/142] db_text : column type comparison compare DB1_STR, DB1_STRING, DB1_BLOB as equal --- modules/db_text/dbt_lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/db_text/dbt_lib.c b/modules/db_text/dbt_lib.c index 32364a04934..7194b6d6d78 100644 --- a/modules/db_text/dbt_lib.c +++ b/modules/db_text/dbt_lib.c @@ -443,13 +443,13 @@ int dbt_is_neq_type(db_type_t _t0, db_type_t _t1) case DB1_DOUBLE: break; case DB1_STRING: - if(_t0==DB1_STR) + if(_t0==DB1_STR || _t0==DB1_BLOB) return 0; case DB1_STR: if(_t0==DB1_STRING || _t0==DB1_BLOB) return 0; case DB1_BLOB: - if(_t0==DB1_STR) + if(_t0==DB1_STR || _t0==DB1_STRING) return 0; case DB1_BITMAP: if (_t0==DB1_INT) From 2809c1eee5d74840ad1974eab09950f2aba3ad31 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Fri, 18 Dec 2015 21:50:02 +0100 Subject: [PATCH 050/142] dispatcher: set sock_avp parameter in example --- modules/dispatcher/doc/dispatcher.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/dispatcher/doc/dispatcher.cfg b/modules/dispatcher/doc/dispatcher.cfg index 8c0fc4c1d7a..08ea285b570 100644 --- a/modules/dispatcher/doc/dispatcher.cfg +++ b/modules/dispatcher/doc/dispatcher.cfg @@ -115,6 +115,7 @@ modparam("dispatcher", "flags", 2) modparam("dispatcher", "dst_avp", "$avp(AVP_DST)") modparam("dispatcher", "grp_avp", "$avp(AVP_GRP)") modparam("dispatcher", "cnt_avp", "$avp(AVP_CNT)") +modparam("dispatcher", "sock_avp", "$avp(AVP_SOCK)") ####### Routing Logic ######## From 981bcc737649796a7cc37e2de564bd1b337675da Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Fri, 18 Dec 2015 21:50:52 +0100 Subject: [PATCH 051/142] dispatcher: readme regenerated with updated config example --- modules/dispatcher/README | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/dispatcher/README b/modules/dispatcher/README index ee38d41b452..efa1c452e90 100644 --- a/modules/dispatcher/README +++ b/modules/dispatcher/README @@ -1373,6 +1373,7 @@ modparam("dispatcher", "flags", 2) modparam("dispatcher", "dst_avp", "$avp(AVP_DST)") modparam("dispatcher", "grp_avp", "$avp(AVP_GRP)") modparam("dispatcher", "cnt_avp", "$avp(AVP_CNT)") +modparam("dispatcher", "sock_avp", "$avp(AVP_SOCK)") ####### Routing Logic ######## From 5937b04a98204fc70ce6db2eab08c038a3497c2a Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 21 Dec 2015 14:48:25 +0100 Subject: [PATCH 052/142] dmq_usrloc: lock before adding contact - reported by GH #440 --- modules/dmq_usrloc/usrloc_sync.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/dmq_usrloc/usrloc_sync.c b/modules/dmq_usrloc/usrloc_sync.c index 15da0756b85..f89500d7efb 100644 --- a/modules/dmq_usrloc/usrloc_sync.c +++ b/modules/dmq_usrloc/usrloc_sync.c @@ -56,10 +56,13 @@ static int add_contact(str aor, ucontact_info_t* ci) str contact; int res; - if (dmq_ul.get_udomain("location", &_d) < 0) { - LM_ERR("Failed to get domain\n"); - return -1; - } + if (dmq_ul.get_udomain("location", &_d) < 0) { + LM_ERR("Failed to get domain\n"); + return -1; + } + + dmq_ul.lock_udomain(_d, &aor); + res = dmq_ul.get_urecord(_d, &aor, &r); if (res < 0) { LM_ERR("failed to retrieve record from usrloc\n"); From b6a4fa2921d531a3dce1277c671942a8c62f3270 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 22 Dec 2015 09:06:01 +0100 Subject: [PATCH 053/142] smsops: changed duplicated section id --- modules/smsops/doc/smsops_admin.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/smsops/doc/smsops_admin.xml b/modules/smsops/doc/smsops_admin.xml index 0772b43f612..b2b2c67b121 100644 --- a/modules/smsops/doc/smsops_admin.xml +++ b/modules/smsops/doc/smsops_admin.xml @@ -77,7 +77,7 @@ if (isRPDATA()) -
+
<function moreinfo="none">smsdump()</function> Dumps the content of a 3GPP-SMS message to the Debug-Log. Please make sure, to have debug-Log enabled. Otherwise, you won't see anything. From a9ec529ecee015e79dc60cb8ba8a6686cdf73a7b Mon Sep 17 00:00:00 2001 From: grumvalski Date: Tue, 22 Dec 2015 13:48:19 +0100 Subject: [PATCH 054/142] cnxcc: define inline functions in cnxcc.h --- modules/cnxcc/cnxcc.c | 24 ------------------------ modules/cnxcc/cnxcc.h | 27 ++++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/modules/cnxcc/cnxcc.c b/modules/cnxcc/cnxcc.c index e869af42048..3d21b3dd7b1 100644 --- a/modules/cnxcc/cnxcc.c +++ b/modules/cnxcc/cnxcc.c @@ -28,30 +28,6 @@ #include "cnxcc.h" -inline void get_datetime(str *dest) -{ - timestamp2isodt(dest, get_current_timestamp()); -} - -inline unsigned int get_current_timestamp() -{ - return time(NULL); -} - -inline int timestamp2isodt(str *dest, unsigned int timestamp) -{ - time_t tim; - struct tm *tmPtr; - - tim = timestamp; - tmPtr = localtime(&tim); - - strftime( dest->s, DATETIME_SIZE, "%Y-%m-%d %H:%M:%S", tmPtr); - dest->len = DATETIME_LENGTH; - - return 0; -} - double str2double(str *string) { char buffer[string->len + 1]; diff --git a/modules/cnxcc/cnxcc.h b/modules/cnxcc/cnxcc.h index 9454e1628fb..3973eabf0a4 100644 --- a/modules/cnxcc/cnxcc.h +++ b/modules/cnxcc/cnxcc.h @@ -31,9 +31,30 @@ #define DATETIME_LENGTH DATETIME_SIZE - 1 -inline void get_datetime(str *dest); -inline unsigned int get_current_timestamp(); -inline int timestamp2isodt(str *dest, unsigned int timestamp); +static inline unsigned int get_current_timestamp() +{ + return time(NULL); +} + +static inline int timestamp2isodt(str *dest, unsigned int timestamp) +{ + time_t tim; + struct tm *tmPtr; + + tim = timestamp; + tmPtr = localtime(&tim); + + strftime( dest->s, DATETIME_SIZE, "%Y-%m-%d %H:%M:%S", tmPtr); + dest->len = DATETIME_LENGTH; + + return 0; +} + +static inline void get_datetime(str *dest) +{ + timestamp2isodt(dest, get_current_timestamp()); +} + double str2double(str *string); #endif /* _CNXCC_H */ From a72e8451aef9391229000cb4e13020f0ff722d92 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 23 Dec 2015 18:10:27 +0100 Subject: [PATCH 055/142] matrix: added section ids for params and functions in docs --- modules/matrix/doc/matrix_admin.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/matrix/doc/matrix_admin.xml b/modules/matrix/doc/matrix_admin.xml index 1424d122ec6..781edc1c355 100644 --- a/modules/matrix/doc/matrix_admin.xml +++ b/modules/matrix/doc/matrix_admin.xml @@ -62,7 +62,7 @@
Parameters -
+
<varname>db_url</varname> (string) The URL for the database connection. @@ -81,7 +81,7 @@ modparam("matrix", "db_url", "&defaultrodb;")
-
+
<varname>matrix_table</varname> (string) The name of the table containing the matrix data. @@ -100,7 +100,7 @@ modparam("matrix", "matrix_table", "matrix")
-
+
<varname>matrix_first_col</varname> (string) The name of the column containing the first row in the matrix. @@ -119,7 +119,7 @@ modparam("matrix", "matrix_first_col", "first")
-
+
<varname>matrix_second_col</varname> (string) The name of the column containing the second row in the matrix. @@ -138,7 +138,7 @@ modparam("matrix", "matrix_second_col", "second")
-
+
<varname>matrix_res_col</varname> (string) The name of the column containing the result ID to be used. @@ -160,7 +160,7 @@ modparam("matrix", "matrix_res_col", "res")
Functions -
+
<function moreinfo="none">matrix (string first, string second, string dstavp)</function> From b51f7822b3e48a18611bed1aaaac5674757f8e33 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 23 Dec 2015 18:11:15 +0100 Subject: [PATCH 056/142] matrix: updates for application name --- modules/matrix/README | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/matrix/README b/modules/matrix/README index 935ab9fcddd..69e50899d0b 100644 --- a/modules/matrix/README +++ b/modules/matrix/README @@ -139,11 +139,11 @@ Chapter 1. Admin Guide The URL for the database connection. - Default value is "mysql://openserro:openserro@localhost/openser". + Default value is "mysql://kamailioro:kamailioro@localhost/kamailio". Example 1.1. Set db_url parameter ... -modparam("matrix", "db_url", "mysql://openserro:openserro@localhost/openser") +modparam("matrix", "db_url", "mysql://kamailioro:kamailioro@localhost/kamailio") ... 3.2. matrix_table (string) @@ -264,7 +264,7 @@ Chapter 2. Module parameter for database access. URL to the database containing the data. - Default value is "mysql://openserro:openserro@localhost/openser". + Default value is "mysql://kamailioro:kamailioro@localhost/kamailio". Example 2.1. Set db_url parameter ... From adcad3445b33d917ef13e4419310b5b11d472fe1 Mon Sep 17 00:00:00 2001 From: lazedo Date: Mon, 28 Dec 2015 04:10:39 +0000 Subject: [PATCH 057/142] presence_dialoginfo : fix memory leak missing xmlFreeDoc from commit b6b7de8832e4ab22ef2c00ebb2c1e1b6ced9ff35 --- modules/presence_dialoginfo/notify_body.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/presence_dialoginfo/notify_body.c b/modules/presence_dialoginfo/notify_body.c index 710fe918235..a701c016451 100644 --- a/modules/presence_dialoginfo/notify_body.c +++ b/modules/presence_dialoginfo/notify_body.c @@ -604,7 +604,7 @@ str *dlginfo_body_setversion(subs_t *subs, str *body) { } pkg_free(aux_body->s); xmlDocDumpFormatMemory(doc,(xmlChar**)(void*)&aux_body->s, &aux_body->len, 1); - + xmlFreeDoc(doc); xmlCleanupParser(); xmlMemoryDump(); From 82d7e06b09f02a2e6dab9f171586f9cd6f636f5b Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 28 Dec 2015 23:11:59 +0100 Subject: [PATCH 058/142] permissions: max size of subnet array set to 512 - was 128, which can be insufficient for large interconnect --- modules/permissions/hash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/permissions/hash.h b/modules/permissions/hash.h index 1823084c88d..cfb6813df00 100644 --- a/modules/permissions/hash.h +++ b/modules/permissions/hash.h @@ -176,7 +176,7 @@ int addr_hash_table_rpc_print(struct addr_list** table, rpc_t* rpc, void* c); void empty_addr_hash_table(struct addr_list** hash_table); -#define PERM_MAX_SUBNETS 128 +#define PERM_MAX_SUBNETS 512 /* From 46b10dfe1941ab70676a10d5f61d749fd74dfa3c Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 28 Dec 2015 23:19:14 +0100 Subject: [PATCH 059/142] permissions: max_subnets - new parameter - specify the max size for address subnets array - default value: 512 - if there are more subnet records in address tables than the value of max_subnets, increase it --- modules/permissions/hash.c | 3 +++ modules/permissions/hash.h | 2 -- modules/permissions/permissions.c | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/permissions/hash.c b/modules/permissions/hash.c index 2aee8b80787..cfc81fe4427 100644 --- a/modules/permissions/hash.c +++ b/modules/permissions/hash.c @@ -44,6 +44,9 @@ static int_str tag_avp; extern int peer_tag_mode; +extern int _perm_max_subnets; + +#define PERM_MAX_SUBNETS _perm_max_subnets /* * Parse and set tag AVP specs diff --git a/modules/permissions/hash.h b/modules/permissions/hash.h index cfb6813df00..0ae7854177a 100644 --- a/modules/permissions/hash.h +++ b/modules/permissions/hash.h @@ -176,8 +176,6 @@ int addr_hash_table_rpc_print(struct addr_list** table, rpc_t* rpc, void* c); void empty_addr_hash_table(struct addr_list** hash_table); -#define PERM_MAX_SUBNETS 512 - /* * Structure used to store a subnet diff --git a/modules/permissions/permissions.c b/modules/permissions/permissions.c index 724e4e8f323..f4133f65fc4 100644 --- a/modules/permissions/permissions.c +++ b/modules/permissions/permissions.c @@ -88,6 +88,8 @@ str port_col = str_init("port"); /* Name of port column */ static int check_all_branches = 1; +int _perm_max_subnets = 512; + /* * Convert the name of the files into table index */ @@ -178,6 +180,7 @@ static param_export_t params[] = { {"ip_addr_col", PARAM_STR, &ip_addr_col }, {"mask_col", PARAM_STR, &mask_col }, {"port_col", PARAM_STR, &port_col }, + {"max_subnets", PARAM_INT, &_perm_max_subnets }, {0, 0, 0} }; From dcb116290209a6b42020a925bc657005c8e3048b Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 28 Dec 2015 23:24:38 +0100 Subject: [PATCH 060/142] permissions: documentation for max_subnets parameter --- modules/permissions/doc/permissions_admin.xml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/modules/permissions/doc/permissions_admin.xml b/modules/permissions/doc/permissions_admin.xml index a38e304497e..6b33e810dc2 100644 --- a/modules/permissions/doc/permissions_admin.xml +++ b/modules/permissions/doc/permissions_admin.xml @@ -769,6 +769,26 @@ modparam("permissions", "peer_tag_avp", "$avp(i:707)") ... modparam("permissions", "peer_tag_mode", 1) ... + + +
+
+ <varname>max_subnets</varname> (int) + + The maximum number of subnet addresses to be loaded from + address table. + + + + Default value is 512. + + + + Set <varname>max_subnets</varname> parameter + +... +modparam("permissions", "max_subnets", 1024) +...
From 1bd8d47148f375462d895ab5bac77eacc965f9c5 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 28 Dec 2015 23:25:01 +0100 Subject: [PATCH 061/142] permissions: regeneration of readme file --- modules/permissions/README | 57 ++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/modules/permissions/README b/modules/permissions/README index bab861a73fe..8c386d42d0d 100644 --- a/modules/permissions/README +++ b/modules/permissions/README @@ -63,6 +63,7 @@ Emmanuel Schmidbauer 3.19. priority_col (string) 3.20. peer_tag_avp (AVP string) 3.21. peer_tag_mode (integer) + 3.22. max_subnets (int) 4. Functions @@ -119,17 +120,18 @@ Emmanuel Schmidbauer 1.19. Set priority_col parameter 1.20. Set peer_tag_avp parameter 1.21. Set peer_tag_mode parameter - 1.22. allow_routing usage - 1.23. allow_routing(basename) usage - 1.24. allow_routing(allow_file, deny_file) usage - 1.25. allow_register(basename) usage - 1.26. allow_register(allow_file, deny_file) usage - 1.27. allow_uri(basename, pvar) usage - 1.28. allow_address() usage - 1.29. allow_source_address(group_id) usage - 1.30. allow_source_address_group() usage + 1.22. Set max_subnets parameter + 1.23. allow_routing usage + 1.24. allow_routing(basename) usage + 1.25. allow_routing(allow_file, deny_file) usage + 1.26. allow_register(basename) usage + 1.27. allow_register(allow_file, deny_file) usage + 1.28. allow_uri(basename, pvar) usage + 1.29. allow_address() usage + 1.30. allow_source_address(group_id) usage 1.31. allow_source_address_group() usage - 1.32. allow_trusted() usage + 1.32. allow_source_address_group() usage + 1.33. allow_trusted() usage Chapter 1. Admin Guide @@ -171,6 +173,7 @@ Chapter 1. Admin Guide 3.19. priority_col (string) 3.20. peer_tag_avp (AVP string) 3.21. peer_tag_mode (integer) + 3.22. max_subnets (int) 4. Functions @@ -403,6 +406,7 @@ Chapter 1. Admin Guide 3.19. priority_col (string) 3.20. peer_tag_avp (AVP string) 3.21. peer_tag_mode (integer) + 3.22. max_subnets (int) 3.1. default_allow_file (string) @@ -683,6 +687,17 @@ modparam("permissions", "peer_tag_avp", "$avp(i:707)") modparam("permissions", "peer_tag_mode", 1) ... +3.22. max_subnets (int) + + The maximum number of subnet addresses to be loaded from address table. + + Default value is "512". + + Example 1.22. Set max_subnets parameter +... +modparam("permissions", "max_subnets", 1024) +... + 4. Functions 4.1. allow_routing() @@ -706,7 +721,7 @@ modparam("permissions", "peer_tag_mode", 1) This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. - Example 1.22. allow_routing usage + Example 1.23. allow_routing usage ... if (allow_routing()) { t_relay(); @@ -729,7 +744,7 @@ if (allow_routing()) { This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. - Example 1.23. allow_routing(basename) usage + Example 1.24. allow_routing(basename) usage ... if (allow_routing("basename")) { t_relay(); @@ -754,7 +769,7 @@ if (allow_routing("basename")) { This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. - Example 1.24. allow_routing(allow_file, deny_file) usage + Example 1.25. allow_routing(allow_file, deny_file) usage ... if (allow_routing("rules.allow", "rules.deny")) { t_relay(); @@ -777,7 +792,7 @@ if (allow_routing("rules.allow", "rules.deny")) { This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. - Example 1.25. allow_register(basename) usage + Example 1.26. allow_register(basename) usage ... if (method=="REGISTER") { if (allow_register("register")) { @@ -807,7 +822,7 @@ if (method=="REGISTER") { This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. - Example 1.26. allow_register(allow_file, deny_file) usage + Example 1.27. allow_register(allow_file, deny_file) usage ... if (method=="REGISTER") { if (allow_register("register.allow", "register.deny")) { @@ -836,7 +851,7 @@ if (method=="REGISTER") { This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. - Example 1.27. allow_uri(basename, pvar) usage + Example 1.28. allow_uri(basename, pvar) usage ... if (allow_uri("basename", "$rt")) { // Check Refer-To URI t_relay(); @@ -862,7 +877,7 @@ if (allow_uri("basename", "$avp(i:705)") { // Check URI stored in $avp(i:705) This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. - Example 1.28. allow_address() usage + Example 1.29. allow_address() usage ... // Check if source address/port is in group 1 @@ -884,7 +899,7 @@ if (!allow_address("2", "$avp(dst_adr)", "$avp(dst_port)") { This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. - Example 1.29. allow_source_address(group_id) usage + Example 1.30. allow_source_address(group_id) usage ... // Check source address/port of request @@ -901,7 +916,7 @@ if (!allow_source_address("1")) { This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. - Example 1.30. allow_source_address_group() usage + Example 1.31. allow_source_address_group() usage ... $var(group) = allow_source_address_group(); @@ -919,7 +934,7 @@ if ($var(group) != -1) { This function can be used from ANY_ROUTE. - Example 1.31. allow_source_address_group() usage + Example 1.32. allow_source_address_group() usage ... $var(group) = allow_address_group("1.2.3.4", "5060"); @@ -944,7 +959,7 @@ if ($var(group) != -1) { This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. - Example 1.32. allow_trusted() usage + Example 1.33. allow_trusted() usage ... if (allow_trusted()) { t_relay(); From 27495c7c34bf963e403c0f711daf9b76076d2ec3 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 29 Dec 2015 23:39:18 +0100 Subject: [PATCH 062/142] tm: silent mode when freeing transactions at shutdown - they are still linked in tm hash table as it should be, so no warn message for that case --- modules/tm/h_table.c | 8 +++++--- modules/tm/h_table.h | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/tm/h_table.c b/modules/tm/h_table.c index 5aee155b459..105230c107d 100644 --- a/modules/tm/h_table.c +++ b/modules/tm/h_table.c @@ -115,7 +115,7 @@ unsigned int transaction_count( void ) -void free_cell_helper( struct cell* dead_cell, const char *fname, unsigned int fline ) +void free_cell_helper(tm_cell_t* dead_cell, int silent, const char *fname, unsigned int fline ) { char *b; int i; @@ -126,8 +126,10 @@ void free_cell_helper( struct cell* dead_cell, const char *fname, unsigned int f LM_DBG("freeing transaction %p from %s:%u\n", dead_cell, fname, fline); if(dead_cell->prev_c!=NULL && dead_cell->next_c!=NULL) { - LM_WARN("removed cell %p is still linked in hash table (%s:%u)\n", + if(likely(silent==0)) { + LM_WARN("removed cell %p is still linked in hash table (%s:%u)\n", dead_cell, fname, fline); + } unlink_timers(dead_cell); remove_from_hash_table_unsafe(dead_cell); } @@ -437,7 +439,7 @@ void free_hash_table( ) /* delete all synonyms at hash-collision-slot i */ clist_foreach_safe(&_tm_table->entries[i], p_cell, tmp_cell, next_c){ - free_cell(p_cell); + free_cell_silent(p_cell); } } shm_free(_tm_table); diff --git a/modules/tm/h_table.h b/modules/tm/h_table.h index 7cda34e1bf0..0cbe24cfebd 100644 --- a/modules/tm/h_table.h +++ b/modules/tm/h_table.h @@ -553,8 +553,9 @@ struct s_table* tm_get_table(void); struct s_table* init_hash_table(void); void free_hash_table(void); -void free_cell_helper( struct cell* dead_cell, const char *fname, unsigned int fline); -#define free_cell(t) free_cell_helper((t), __FILE__, __LINE__) +void free_cell_helper(tm_cell_t* dead_cell, int silent, const char *fname, unsigned int fline); +#define free_cell(t) free_cell_helper((t), 0, __FILE__, __LINE__) +#define free_cell_silent(t) free_cell_helper((t), 1, __FILE__, __LINE__) struct cell* build_cell( struct sip_msg* p_msg ); From f0b5fa7415d81cfc6df1e4dd51cd508898df5419 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 29 Dec 2015 23:48:39 +0100 Subject: [PATCH 063/142] tsilo: init and safety check for t value before unref --- modules/tsilo/ts_append.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/tsilo/ts_append.c b/modules/tsilo/ts_append.c index 3c476630da7..db47fdfad7d 100644 --- a/modules/tsilo/ts_append.c +++ b/modules/tsilo/ts_append.c @@ -82,7 +82,7 @@ int ts_append(struct sip_msg* msg, str *ruri, char *table) { } int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri) { - struct cell *t; + struct cell *t=0; struct cell *orig_t; struct sip_msg *orig_msg; int ret; @@ -130,7 +130,7 @@ int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str * done: /* unref the transaction which had been referred by t_lookup_ident() call. * Restore the original transaction (if any) */ - _tmb.unref_cell(t); + if(t) _tmb.unref_cell(t); _tmb.t_sett(orig_t, T_BR_UNDEFINED); return ret; From d83a56bcdfeb8ffc75166a62e11ceb4c057c3ce5 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 30 Dec 2015 00:29:49 +0100 Subject: [PATCH 064/142] tm: don't free tm cell still linked in wait timer - wait timer should do the free - friendlier handling of situation when modules binding to tm do inconsistent unref operations --- modules/tm/h_table.c | 6 ++++++ modules/tm/t_funcs.c | 6 ++++++ modules/tm/t_funcs.h | 1 + 3 files changed, 13 insertions(+) diff --git a/modules/tm/h_table.c b/modules/tm/h_table.c index 105230c107d..ea38de01fc8 100644 --- a/modules/tm/h_table.c +++ b/modules/tm/h_table.c @@ -40,6 +40,7 @@ #include "t_reply.h" #include "t_cancel.h" #include "t_stats.h" +#include "t_funcs.h" #include "h_table.h" #include "../../fix_lumps.h" /* free_via_clen_lump */ #include "timer.h" @@ -129,6 +130,11 @@ void free_cell_helper(tm_cell_t* dead_cell, int silent, const char *fname, unsig if(likely(silent==0)) { LM_WARN("removed cell %p is still linked in hash table (%s:%u)\n", dead_cell, fname, fline); + if(t_on_wait(dead_cell)) { + LM_WARN("cell %p is still linked in wait timer (%s:%u)" + " - skip freeing now\n", dead_cell, fname, fline); + return; + } } unlink_timers(dead_cell); remove_from_hash_table_unsafe(dead_cell); diff --git a/modules/tm/t_funcs.c b/modules/tm/t_funcs.c index cec58e03a65..e498713a3b6 100644 --- a/modules/tm/t_funcs.c +++ b/modules/tm/t_funcs.c @@ -150,6 +150,12 @@ void put_on_wait( struct cell *Trans ) } +int t_on_wait(tm_cell_t *Trans) +{ + if(Trans->wait_timer.prev!=NULL || Trans->wait_timer.next!=NULL) + return 1; + return 0; +} /* WARNING: doesn't work from failure route (deadlock, uses t_reply => * tries to get the reply lock again) */ diff --git a/modules/tm/t_funcs.h b/modules/tm/t_funcs.h index 173851bca67..b7b653e9131 100644 --- a/modules/tm/t_funcs.h +++ b/modules/tm/t_funcs.h @@ -190,6 +190,7 @@ int get_ip_and_port_from_uri( str* uri , unsigned int *param_ip, void put_on_wait( struct cell *Trans ); +int t_on_wait(tm_cell_t *Trans); int t_relay_to( struct sip_msg *p_msg , From f703effa2e2d6c6f426374d07d57636ecf248fd2 Mon Sep 17 00:00:00 2001 From: Phil Lavin Date: Wed, 30 Dec 2015 09:00:45 +0000 Subject: [PATCH 065/142] auth_radius: support for not appending realm to the username passed to RADIUS - Implement append_realm_to_username parameter in auth_radius which allows the unmolested digest username to be passed to RADIUS in the User-Name attribute. This is required for some RADIUS implementations. --- modules/auth_radius/authrad_mod.c | 2 ++ modules/auth_radius/authrad_mod.h | 1 + modules/auth_radius/doc/auth_radius.xml | 5 +++++ modules/auth_radius/doc/auth_radius_admin.xml | 17 +++++++++++++++++ modules/auth_radius/sterman.c | 2 +- 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/modules/auth_radius/authrad_mod.c b/modules/auth_radius/authrad_mod.c index f4a9eac81e8..94ca865712c 100644 --- a/modules/auth_radius/authrad_mod.c +++ b/modules/auth_radius/authrad_mod.c @@ -66,6 +66,7 @@ static int service_type = -1; int use_ruri_flag = -1; int ar_radius_avps_mode = 0; +int append_realm_to_username = 1; static char *auth_extra_str = 0; struct extra_attr *auth_extra = 0; @@ -95,6 +96,7 @@ static param_export_t params[] = { {"use_ruri_flag", INT_PARAM, &use_ruri_flag }, {"auth_extra", PARAM_STRING, &auth_extra_str }, {"radius_avps_mode", INT_PARAM, &ar_radius_avps_mode }, + {"append_realm_to_username", INT_PARAM, &append_realm_to_username }, {0, 0, 0} }; diff --git a/modules/auth_radius/authrad_mod.h b/modules/auth_radius/authrad_mod.h index c6561d3d24a..ac8fe011bf8 100644 --- a/modules/auth_radius/authrad_mod.h +++ b/modules/auth_radius/authrad_mod.h @@ -41,6 +41,7 @@ extern struct extra_attr *auth_extra; extern int use_ruri_flag; extern int ar_radius_avps_mode; +extern int append_realm_to_username; extern auth_api_s_t auth_api; diff --git a/modules/auth_radius/doc/auth_radius.xml b/modules/auth_radius/doc/auth_radius.xml index 5ae4e280ba8..fd02edc1bfa 100644 --- a/modules/auth_radius/doc/auth_radius.xml +++ b/modules/auth_radius/doc/auth_radius.xml @@ -38,6 +38,11 @@ Janak jan@iptel.org + + Phil + Lavin + phil.lavin@synety.com + 2002 diff --git a/modules/auth_radius/doc/auth_radius_admin.xml b/modules/auth_radius/doc/auth_radius_admin.xml index 79771625d0c..0475d5746e9 100644 --- a/modules/auth_radius/doc/auth_radius_admin.xml +++ b/modules/auth_radius/doc/auth_radius_admin.xml @@ -206,6 +206,23 @@ modparam("auth_radius", "radius_avps_mode", 1)
+
+ <varname>append_realm_to_username</varname> (integer) + + If set to 1, the username passed to the RADIUS server will have the + digest realm appended to it, if no domain is provided in the digest + username. + + + Default value is 1. + + + <varname>append_realm_to_username</varname> parameter usage + +modparam("auth_radius", "append_realm_to_username", 0) + + +
diff --git a/modules/auth_radius/sterman.c b/modules/auth_radius/sterman.c index 88eef1d9a66..f95fdbc2e1c 100644 --- a/modules/auth_radius/sterman.c +++ b/modules/auth_radius/sterman.c @@ -243,7 +243,7 @@ int radius_authorize_sterman(struct sip_msg* _msg, dig_cred_t* _cred, str* _meth * Add all the user digest parameters according to the qop defined. * Most devices tested only offer support for the simplest digest. */ - if (_cred->username.domain.len) { + if (_cred->username.domain.len || !append_realm_to_username) { if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, _cred->username.whole.s, _cred->username.whole.len, 0)) { LM_ERR("unable to add User-Name attribute\n"); goto err; From 94da0d648805b958d266b789015f66cef8628ae4 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 30 Dec 2015 17:41:18 +0100 Subject: [PATCH 066/142] tsilo: check if tsilo hash table is still set when executing tm callback - freeing the transaction structure by tm at shutdown can execute this callback, resulting in core dump (at shutdonw) if tsilo destroyed its hash table already --- modules/tsilo/ts_handlers.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/tsilo/ts_handlers.c b/modules/tsilo/ts_handlers.c index c04ec360fd3..392c71aed88 100644 --- a/modules/tsilo/ts_handlers.c +++ b/modules/tsilo/ts_handlers.c @@ -25,6 +25,7 @@ #include "ts_handlers.h" extern struct tm_binds _tmb; +extern struct ts_table *t_table; /*! * \brief add transaction structure to tm callbacks @@ -61,6 +62,8 @@ void ts_onreply(struct cell* t, int type, struct tmcb_params *param) ts_entry_t* _e; ts_transaction_t *cb_ptr, *ptr; + if(t_table==0) return; + cb_ptr = (ts_transaction_t*)(*param->param); if (cb_ptr == NULL) { LM_DBG("NULL param for type %d\n", type); From c7e411edb3c68260d43f86ee6977d468c074836b Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 30 Dec 2015 21:18:23 +0100 Subject: [PATCH 067/142] tm: reinit ref counter if attempting to free while still in wait timer --- modules/tm/h_table.c | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/tm/h_table.c b/modules/tm/h_table.c index ea38de01fc8..d492665be9c 100644 --- a/modules/tm/h_table.c +++ b/modules/tm/h_table.c @@ -131,6 +131,7 @@ void free_cell_helper(tm_cell_t* dead_cell, int silent, const char *fname, unsig LM_WARN("removed cell %p is still linked in hash table (%s:%u)\n", dead_cell, fname, fline); if(t_on_wait(dead_cell)) { + INIT_REF(dead_cell, 1); LM_WARN("cell %p is still linked in wait timer (%s:%u)" " - skip freeing now\n", dead_cell, fname, fline); return; From 97a921ca63bd5482a690fe8ba399b05fd0134129 Mon Sep 17 00:00:00 2001 From: lazedo Date: Mon, 4 Jan 2016 05:12:42 +0000 Subject: [PATCH 068/142] db_text: add support for replace implements replace with update/insert tries to update, inserts if not found --- modules/db_text/dbt_base.c | 129 +++++++++++++++++++++++++++++++++++++ modules/db_text/dbtext.c | 3 +- modules/db_text/dbtext.h | 6 ++ 3 files changed, 137 insertions(+), 1 deletion(-) diff --git a/modules/db_text/dbt_base.c b/modules/db_text/dbt_base.c index 6d70ce543b3..4ab9a1652c0 100644 --- a/modules/db_text/dbt_base.c +++ b/modules/db_text/dbt_base.c @@ -617,3 +617,132 @@ int dbt_update(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, return -1; } +int dbt_replace(db1_con_t* _h, db_key_t* _k, db_val_t* _v, + int _n, int _nk, int _m) +{ + dbt_table_p _tbc = NULL; + dbt_row_p _drp = NULL; + int i, j; + int *lkey=NULL, *lres=NULL; + + if (!_h || !CON_TABLE(_h) || _nk <= 0) + { + LM_ERR("invalid parameters\n"); + return -1; + } + + ((dbt_con_p)_h->tail)->affected = 0; + + /* lock database */ + _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + if(!_tbc) + { + LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s); + return -1; + } + + if(_k) + { + lkey = dbt_get_refs(_tbc, _k, _nk); + if(!lkey) + goto error; + } + lres = dbt_get_refs(_tbc, _k, _n); + if(!lres) + goto error; + _drp = _tbc->rows; + while(_drp) + { + if(dbt_row_match(_tbc, _drp, lkey, NULL, _v, _nk)) + { // update fields + for(i=0; i<_n; i++) + { + if(dbt_is_neq_type(_tbc->colv[lres[i]]->type, _v[i].type)) + { + LM_ERR("incompatible types!\n"); + goto error; + } + + if(dbt_row_update_val(_drp, &(_v[i]), + _tbc->colv[lres[i]]->type, lres[i])) + { + LM_ERR("cannot set v[%d] in c[%d]!\n", + i, lres[i]); + goto error; + } + } + + ((dbt_con_p)_h->tail)->affected++; + + } + _drp = _drp->next; + } + + if(((dbt_con_p)_h->tail)->affected == 0) { + _drp = dbt_row_new(_tbc->nrcols); + if(!_drp) + { + LM_ERR("no shm memory for a new row!!\n"); + goto error; + } + + for(i=0; i<_n; i++) + { + j = lres[i]; + if(dbt_is_neq_type(_tbc->colv[j]->type, _v[i].type)) + { + LM_ERR("incompatible types v[%d] - c[%d]!\n", i, j); + goto error; + } + if(_v[i].type == DB1_STRING && !_v[i].nul) + _v[i].val.str_val.len = strlen(_v[i].val.string_val); + if(dbt_row_set_val(_drp, &(_v[i]), _tbc->colv[j]->type, j)) + { + LM_ERR("cannot set v[%d] in c[%d]!\n", i, j); + goto error; + } + } + + if(dbt_table_add_row(_tbc, _drp)) + { + LM_ERR("cannot insert the new row!!\n"); + goto error; + } + + ((dbt_con_p)_h->tail)->affected = 1; + + } + + if( ((dbt_con_p)_h->tail)->affected ) + dbt_table_update_flags(_tbc, DBT_TBFL_MODI, DBT_FL_SET, 1); + + /* dbt_print_table(_tbc, NULL); */ + + /* unlock database */ + dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + + if(lkey) + pkg_free(lkey); + if(lres) + pkg_free(lres); + + return 0; + +error: + + if(lkey) + pkg_free(lkey); + if(lres) + pkg_free(lres); + if(_drp) // free row + dbt_row_free(_tbc, _drp); + + /* unlock database */ + dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + + LM_ERR("failed to update the table!\n"); + + return -1; +} + + diff --git a/modules/db_text/dbtext.c b/modules/db_text/dbtext.c index 4f1d4a6a65d..f601398172b 100644 --- a/modules/db_text/dbtext.c +++ b/modules/db_text/dbtext.c @@ -125,9 +125,10 @@ int dbt_bind_api(db_func_t *dbb) dbb->insert = (db_insert_f)dbt_insert; dbb->delete = (db_delete_f)dbt_delete; dbb->update = (db_update_f)dbt_update; + dbb->replace = (db_replace_f)dbt_replace; dbb->affected_rows = (db_affected_rows_f) dbt_affected_rows; dbb->raw_query = (db_raw_query_f) dbt_raw_query; - dbb->cap = DB_CAP_ALL | DB_CAP_AFFECTED_ROWS | DB_CAP_RAW_QUERY; + dbb->cap = DB_CAP_ALL | DB_CAP_AFFECTED_ROWS | DB_CAP_RAW_QUERY | DB_CAP_REPLACE; return 0; } diff --git a/modules/db_text/dbtext.h b/modules/db_text/dbtext.h index 92e62361a73..5cbacae18af 100644 --- a/modules/db_text/dbtext.h +++ b/modules/db_text/dbtext.h @@ -81,6 +81,12 @@ int dbt_delete(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n); int dbt_update(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, db_key_t* _uk, db_val_t* _uv, int _n, int _un); +/* + * replace a row in table + */ +int dbt_replace(db1_con_t* _h, db_key_t* _k, db_val_t* _v, + int _n, int _nk, int _m); + /* * Affected rows */ From ad168dd580d21e1896c21a41b91b7eee5e5e7f8b Mon Sep 17 00:00:00 2001 From: lazedo Date: Mon, 4 Jan 2016 05:17:09 +0000 Subject: [PATCH 069/142] presence: additional info in logs adds callid to NOTIFY log adds log when multiple records are found in process_dialogs --- modules/presence/notify.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/modules/presence/notify.c b/modules/presence/notify.c index f6a0ba9548e..d92182b1ccc 100644 --- a/modules/presence/notify.c +++ b/modules/presence/notify.c @@ -1612,11 +1612,12 @@ int send_notify_request(subs_t* subs, subs_t * watcher_subs, } LM_GEN1(pres_local_log_level, - "NOTIFY %.*s via %.*s on behalf of %.*s for event %.*s\n", + "NOTIFY %.*s via %.*s on behalf of %.*s for event %.*s : %.*s\n", td->rem_uri.len, td->rem_uri.s, td->hooks.next_hop->len, td->hooks.next_hop->s, - td->loc_uri.len, td->loc_uri.s, subs->event->name.len, - subs->event->name.s); + td->loc_uri.len, td->loc_uri.s, + subs->event->name.len, subs->event->name.s, + subs->callid.len, subs->callid.s); ps_free_tm_dlg(td); @@ -2859,7 +2860,13 @@ int process_dialogs(int round, int presence_winfo) if (dialog->n > 1) { - LM_ERR("multiple records found\n"); + LM_ERR("multiple records found for %.*s, ci : %.*s, tt : %.*s, ft : %.*s, ev : %.*s\n", + sub.pres_uri.len, sub.pres_uri.s, + sub.callid.len, sub.callid.s, + sub.to_tag.len, sub.to_tag.s, + sub.from_tag.len, sub.from_tag.s, + ev_sname.len, ev_sname.s + ); goto delete_dialog; } From bb2c9ea0b70a428dd115da5fa2c0e6482d9db7dc Mon Sep 17 00:00:00 2001 From: lazedo Date: Mon, 4 Jan 2016 16:12:46 +0000 Subject: [PATCH 070/142] presence_xml: fix pres_agg_nbody_empty we were sending the presence element without the entity attribute. it seems some UAs dislike this --- modules/presence_xml/notify_body.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/presence_xml/notify_body.c b/modules/presence_xml/notify_body.c index 2730038ae89..f10305cfb31 100644 --- a/modules/presence_xml/notify_body.c +++ b/modules/presence_xml/notify_body.c @@ -58,15 +58,20 @@ void free_xml_body(char* body) body= NULL; } -#define PRESENCE_EMPTY_BODY_SIZE 512 +#define PRESENCE_EMPTY_BODY_SIZE 1024 -#define PRESENCE_EMPTY_BODY " \ -\ +#define PRESENCE_EMPTY_BODY "\ + \ +\ \ open\ \ \ Available\ +\ +\ +Available\ +\ " str* pres_agg_nbody_empty(str* pres_user, str* pres_domain) @@ -78,7 +83,7 @@ str* pres_agg_nbody_empty(str* pres_user, str* pres_domain) str* body_array = (str*)pkg_malloc(sizeof(str)); char* body = (char*)pkg_malloc(PRESENCE_EMPTY_BODY_SIZE); - sprintf(body, PRESENCE_EMPTY_BODY); + sprintf(body, PRESENCE_EMPTY_BODY, pres_user->len, pres_user->s); body_array->s = body; body_array->len = strlen(body); From 96d0b4ecff3cd680861bbc2ac02151a77cb05cae Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 4 Jan 2016 19:19:35 +0100 Subject: [PATCH 071/142] presence_xml: safety checks for pkg alloc and buffer size --- modules/presence_xml/notify_body.c | 32 +++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/modules/presence_xml/notify_body.c b/modules/presence_xml/notify_body.c index f10305cfb31..bba3687809e 100644 --- a/modules/presence_xml/notify_body.c +++ b/modules/presence_xml/notify_body.c @@ -78,12 +78,31 @@ str* pres_agg_nbody_empty(str* pres_user, str* pres_domain) { str* n_body= NULL; + str* body_array; + char* body; + LM_DBG("creating empty presence for [pres_user]=%.*s [pres_domain]= %.*s\n", pres_user->len, pres_user->s, pres_domain->len, pres_domain->s); - str* body_array = (str*)pkg_malloc(sizeof(str)); - char* body = (char*)pkg_malloc(PRESENCE_EMPTY_BODY_SIZE); - sprintf(body, PRESENCE_EMPTY_BODY, pres_user->len, pres_user->s); + if(pres_user->len+sizeof(PRESENCE_EMPTY_BODY) + >= PRESENCE_EMPTY_BODY_SIZE - 1) { + LM_ERR("insufficient buffer to add user (its len is: %d)\n", + pres_user->len); + return NULL; + } + body_array = (str*)pkg_malloc(sizeof(str)); + if(body_array==NULL) { + LM_ERR("no more pkg\n"); + return NULL; + } + + body = (char*)pkg_malloc(PRESENCE_EMPTY_BODY_SIZE); + if(body_array==NULL) { + LM_ERR("no more pkg\n"); + pkg_free(body_array); + return NULL; + } + snprintf(body, PRESENCE_EMPTY_BODY_SIZE, PRESENCE_EMPTY_BODY, pres_user->len, pres_user->s); body_array->s = body; body_array->len = strlen(body); @@ -91,11 +110,10 @@ str* pres_agg_nbody_empty(str* pres_user, str* pres_domain) n_body= agregate_xmls(pres_user, pres_domain, &body_array, 1); LM_DBG("[n_body]=%p\n", n_body); if(n_body) { - LM_DBG("[*n_body]=%.*s\n",n_body->len, n_body->s); + LM_DBG("[*n_body]=%.*s\n", n_body->len, n_body->s); } - if(n_body== NULL) - { - LM_ERR("while aggregating body\n"); + if(n_body== NULL) { + LM_ERR("while aggregating body for: %.*s\n", pres_user->len, pres_user->s); } pkg_free(body); From 6fe2b87e1a6dff2a4351d83e91bd0de809530241 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 4 Jan 2016 22:56:55 +0100 Subject: [PATCH 072/142] core: fixed debug message warning --- socket_info.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/socket_info.c b/socket_info.c index e2d914734dc..d06fdcfd2c8 100644 --- a/socket_info.c +++ b/socket_info.c @@ -1221,7 +1221,9 @@ int add_interfaces(char* if_name, int family, unsigned short port, ret = -1; break; } - LM_DBG("If: %8s Fam: %8x Flg: %16lx Adr: %s\n", ifa->ifa_name, ifa->ifa_addr->sa_family, ifa->ifa_flags, tmp); + LM_DBG("If: %8s Fam: %8x Flg: %16lx Adr: %s\n", + ifa->ifa_name, ifa->ifa_addr->sa_family, + (unsigned long)ifa->ifa_flags, tmp); ret = 0; } From fa6465f92adf372c3307211a05688a2482d89353 Mon Sep 17 00:00:00 2001 From: Armen Babikyan Date: Mon, 4 Jan 2016 23:04:37 +0100 Subject: [PATCH 073/142] core: added event callback field for tcp closed connection --- events.c | 13 +++++++++++++ events.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/events.c b/events.c index 5312e7a5ba7..bb1373afcc2 100644 --- a/events.c +++ b/events.c @@ -165,6 +165,11 @@ int sr_event_register_cb(int type, sr_event_cb_f f) _sr_events_list.rcv_nosip = f; else return -1; break; + case SREV_TCP_CLOSED: + if(_sr_events_list.tcp_closed==0) + _sr_events_list.tcp_closed = f; + else return -1; + break; default: return -1; } @@ -284,6 +289,12 @@ int sr_event_exec(int type, void *data) ret = _sr_events_list.rcv_nosip(data); return ret; } else return 1; + case SREV_TCP_CLOSED: + if(unlikely(_sr_events_list.tcp_closed!=0)) + { + ret = _sr_events_list.tcp_closed(data); + return ret; + } else return 1; default: return -1; } @@ -319,6 +330,8 @@ int sr_event_enabled(int type) return (_sr_events_list.stun_in!=0)?1:0; case SREV_RCV_NOSIP: return (_sr_events_list.rcv_nosip!=0)?1:0; + case SREV_TCP_CLOSED: + return (_sr_events_list.tcp_closed!=0)?1:0; } return 0; } diff --git a/events.h b/events.h index 821845366d8..2946d940ecc 100644 --- a/events.h +++ b/events.h @@ -34,6 +34,7 @@ #define SREV_TCP_WS_FRAME_IN 10 #define SREV_TCP_WS_FRAME_OUT 11 #define SREV_STUN_IN 12 +#define SREV_TCP_CLOSED 13 #define SREV_CB_LIST_SIZE 3 @@ -52,6 +53,7 @@ typedef struct sr_event_cb { sr_event_cb_f tcp_ws_frame_out; sr_event_cb_f stun_in; sr_event_cb_f rcv_nosip; + sr_event_cb_f tcp_closed; } sr_event_cb_t; void sr_event_cb_init(void); From 1980c79d4fb2111c8c245045035f4ecb5d17fd7f Mon Sep 17 00:00:00 2001 From: Armen Babikyan Date: Mon, 4 Jan 2016 23:05:30 +0100 Subject: [PATCH 074/142] core: trigger event_route execution for unexpectedly-closed and client-closed tcp connections --- tcp_read.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tcp_read.c b/tcp_read.c index bf075740802..84ddf90ffc3 100644 --- a/tcp_read.c +++ b/tcp_read.c @@ -186,6 +186,25 @@ int tcp_http11_continue(struct tcp_connection *c) } #endif /* HTTP11 */ +static int tcp_make_closed_event(struct receive_info* rcv_info, struct tcp_connection* con) +{ + int ret; + tcp_event_info_t tev; + + ret = 0; + LM_DBG("TCP closed event creation triggered\n"); + if(likely(sr_event_enabled(SREV_TCP_CLOSED))) { + memset(&tev, 0, sizeof(tcp_event_info_t)); + tev.type = SREV_TCP_CLOSED; + tev.rcv = rcv_info; + tev.con = con; + ret = sr_event_exec(SREV_TCP_CLOSED, (void*)(&tev)); + } else { + LM_DBG("no callback registering for handling TCP closed event - dropping!\n"); + } + return ret; +} + /** reads data from an existing tcp connection. * Side-effects: blacklisting, sets connection state to S_CONN_OK, tcp stats. @@ -272,12 +291,20 @@ int tcp_read_data(int fd, struct tcp_connection *c, strerror(errno), errno, ip_addr2a(&c->rcv.src_ip), c->rcv.src_port, ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); + + if((errno == ECONNRESET || errno == ETIMEDOUT) && likely(c->rcv.proto_reserved1 != 0)){ + tcp_make_closed_event(&c->rcv, c); + } + return -1; } }else if (unlikely((bytes_read==0) || (*flags & RD_CONN_FORCE_EOF))){ c->state=S_CONN_EOF; *flags|=RD_CONN_EOF; + if (likely(c->rcv.proto_reserved1 != 0)){ + tcp_make_closed_event(&c->rcv, c); + } LM_DBG("EOF on %p, FD %d ([%s]:%u -> [%s]:%u)\n", c, fd, ip_addr2a(&c->rcv.src_ip), c->rcv.src_port, ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); From 5856d9848345a429c0a7bd91a6d9eccf45d067d3 Mon Sep 17 00:00:00 2001 From: Armen Babikyan Date: Mon, 4 Jan 2016 23:06:52 +0100 Subject: [PATCH 075/142] tcpops: framework to execute event_route[tcp:closed] --- modules/tcpops/tcpops.c | 44 +++++++++++++++++++++++++++++++++++++ modules/tcpops/tcpops.h | 2 ++ modules/tcpops/tcpops_mod.c | 6 +++++ 3 files changed, 52 insertions(+) diff --git a/modules/tcpops/tcpops.c b/modules/tcpops/tcpops.c index 037a8cb668d..d89e01abe87 100644 --- a/modules/tcpops/tcpops.c +++ b/modules/tcpops/tcpops.c @@ -31,6 +31,7 @@ #include "../../globals.h" #include "../../pass_fd.h" #include "../../timer.h" +#include "../../sr_module.h" /** * gets the fd of the current message source connection @@ -185,3 +186,46 @@ int tcpops_set_connection_lifetime(struct tcp_connection* con, int time) { LM_DBG("new connection lifetime for conid=%d: %d\n", con->id, con->timeout); return 1; } + +static void tcpops_tcp_closed_run_route(struct tcp_connection *con) +{ + int rt, backup_rt; + struct run_act_ctx ctx; + sip_msg_t *fmsg; + LM_DBG("tcp_closed_run_route event_route[tcp:closed]\n"); + + rt = route_get(&event_rt, "tcp:closed"); + if (rt < 0 || event_rt.rlist[rt] == NULL) + { + LM_DBG("route does not exist"); + return; + } + + if (faked_msg_init() < 0) + { + LM_ERR("faked_msg_init() failed\n"); + return; + } + fmsg = faked_msg_next(); + fmsg->rcv = con->rcv; + + backup_rt = get_route_type(); + set_route_type(EVENT_ROUTE); + init_run_actions_ctx(&ctx); + run_top_route(event_rt.rlist[rt], fmsg, 0); + set_route_type(backup_rt); +} + +int tcpops_handle_tcp_closed(void *data) +{ + tcp_event_info_t *tev = (tcp_event_info_t *) data; + + if (tev == NULL || tev->con == NULL) { + LM_WARN("received bad TCP closed event\n"); + return -1; + } + + tcpops_tcp_closed_run_route(tev->con); + + return 0; +} diff --git a/modules/tcpops/tcpops.h b/modules/tcpops/tcpops.h index c9a07716c9e..771516f0d02 100644 --- a/modules/tcpops/tcpops.h +++ b/modules/tcpops/tcpops.h @@ -25,11 +25,13 @@ #define TCP_KEEPALIVE_H_ #include "../../tcp_conn.h" +#include "../../events.h" int tcpops_get_current_fd(int conid, int *fd); int tcpops_acquire_fd_from_tcpmain(int conid, int *fd); int tcpops_keepalive_enable(int fd, int idle, int count, int interval, int closefd); int tcpops_keepalive_disable(int fd, int closefd); int tcpops_set_connection_lifetime(struct tcp_connection* con, int time); +int tcpops_handle_tcp_closed(void *data); #endif /* TCP_KEEPALIVE_H_ */ diff --git a/modules/tcpops/tcpops_mod.c b/modules/tcpops/tcpops_mod.c index c40002023d2..0de40c70538 100644 --- a/modules/tcpops/tcpops_mod.c +++ b/modules/tcpops/tcpops_mod.c @@ -35,6 +35,7 @@ #include "../../tcp_options.h" #include "../../dprint.h" #include "../../mod_fix.h" +#include "../../events.h" #include "tcpops.h" @@ -101,6 +102,11 @@ static int mod_init(void) { LM_DBG("TCP keepalive module loaded.\n"); + if (sr_event_register_cb(SREV_TCP_CLOSED, tcpops_handle_tcp_closed) != 0) { + LM_ERR("problem registering tcpops_handle_tcp_closed call-back\n"); + return -1; + } + return 0; } From bef6dd6bb52921a703db295ff7736ea5a8ad212e Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 4 Jan 2016 23:10:01 +0100 Subject: [PATCH 076/142] tcpops: include header for faked message to get rid of compile warnings - warnings resulted after the commit for event_route[tcp:closed] --- modules/tcpops/tcpops.c | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/tcpops/tcpops.c b/modules/tcpops/tcpops.c index d89e01abe87..b407e130f2e 100644 --- a/modules/tcpops/tcpops.c +++ b/modules/tcpops/tcpops.c @@ -31,6 +31,7 @@ #include "../../globals.h" #include "../../pass_fd.h" #include "../../timer.h" +#include "../../fmsg.h" #include "../../sr_module.h" /** From 36629c11ff9fb3999f3ebf298a9e87bb2abc4885 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Tue, 29 Dec 2015 13:07:42 +0200 Subject: [PATCH 077/142] debugger: fifo module level/facility setters Add kamctl fifo module level/facility setters. --- modules/debugger/Makefile | 1 + modules/debugger/debugger_api.c | 1 + modules/debugger/debugger_mod.c | 138 +++++++++++++++++++++++++++++++- 3 files changed, 139 insertions(+), 1 deletion(-) diff --git a/modules/debugger/Makefile b/modules/debugger/Makefile index abf9d352c18..6ea383219f8 100644 --- a/modules/debugger/Makefile +++ b/modules/debugger/Makefile @@ -10,4 +10,5 @@ DEFS+=-DKAMAILIO_MOD_INTERFACE SERLIBPATH=../../lib SER_LIBS+=$(SERLIBPATH)/srutils/srutils +SER_LIBS+=$(SERLIBPATH)/kmi/kmi include ../../Makefile.modules diff --git a/modules/debugger/debugger_api.c b/modules/debugger/debugger_api.c index d0ce44fd205..014d5be1640 100644 --- a/modules/debugger/debugger_api.c +++ b/modules/debugger/debugger_api.c @@ -1138,6 +1138,7 @@ int dbg_init_mod_levels(int dbg_mod_hash_size) return -1; } memset(_dbg_mod_table, 0, _dbg_mod_table_size*sizeof(dbg_mod_slot_t)); + LM_DBG("Created _dbg_mod_table, size %d\n", _dbg_mod_table_size); for(i=0; i<_dbg_mod_table_size; i++) { diff --git a/modules/debugger/debugger_mod.c b/modules/debugger/debugger_mod.c index fd1d91bdd28..a343bba8cbe 100644 --- a/modules/debugger/debugger_mod.c +++ b/modules/debugger/debugger_mod.c @@ -28,6 +28,8 @@ #include #include "../cfgt/cfgt.h" +#include "../../lib/kmi/mi.h" +#include "../../lib/kmi/tree.h" #include "../../sr_module.h" #include "../../dprint.h" #include "../../ut.h" @@ -61,6 +63,10 @@ static int w_dbg_sip_msg(struct sip_msg* msg, char *level, char *facility); extern char* dump_lump_list(struct lump *list, int s_offset, char *s_buf); +/* mi commands */ +static struct mi_root* mi_set_dbg_mod_level(struct mi_root *cmd_tree, void *param); +static struct mi_root* mi_set_dbg_mod_facility(struct mi_root *cmd_tree, void *param); + /* parameters */ extern int _dbg_cfgtrace; extern int _dbg_cfgpkgcheck; @@ -120,13 +126,19 @@ static param_export_t params[]={ {0, 0, 0} }; +static mi_export_t mi_cmds[] = { + {"set_dbg_mod_level", mi_set_dbg_mod_level, 0, 0, 0}, + {"set_dbg_mod_facility", mi_set_dbg_mod_facility, 0, 0, 0}, + { 0, 0, 0, 0, 0} +}; + struct module_exports exports = { "debugger", DEFAULT_DLFLAGS, /* dlopen flags */ cmds, params, 0, - 0, /* exported MI functions */ + mi_cmds, /* exported MI functions */ 0, /* exported pseudo-variables */ 0, /* extra processes */ mod_init, /* module initialization function */ @@ -136,6 +148,124 @@ struct module_exports exports = { }; +static struct mi_root* mi_set_dbg_mod_level(struct mi_root *cmd_tree, void *param) { + struct mi_node *node; + str mod_str, level_str; + int l; + + /* get first param */ + node = cmd_tree->node.kids; + if (node == NULL) { + return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); + } + + if (node->value.s == NULL || node->value.len == 0) { + return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); + } + + /* get module str */ + mod_str = node->value; + + /* get second param */ + node = node->next; + if (node == NULL) { + return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); + } + + if (node->value.s == NULL || node->value.len == 0) { + return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); + } + + /* get level str */ + level_str = node->value; + + /* no further params expected */ + node = node->next; + if (node != NULL) { + return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); + } + + /* get level int */ + if (str2sint(&level_str, &l) < 0) { + LM_ERR("invalid parameter - level value: %.*s\n", + level_str.len, level_str.s); + return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); + } + + /* set level int */ + if (default_dbg_cfg.mod_hash_size <= 0 || default_dbg_cfg.mod_level_mode <= 0 || + dbg_set_mod_debug_level(mod_str.s, mod_str.len, &l) < 0) { + LM_ERR("cannot set level for %.*s; enable mod_hash_size and mod_level_mode\n", + mod_str.len, mod_str.s); + return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN); + } else { + LM_DBG("module=%.*s level_str=%.*s level_int=%d\n", + mod_str.len, mod_str.s, level_str.len, level_str.s, l); + } + + return init_mi_tree(200, MI_OK_S, MI_OK_LEN); +} + +static struct mi_root* mi_set_dbg_mod_facility(struct mi_root *cmd_tree, void *param) { + struct mi_node *node; + str mod_str, facility_str; + int fl; + + /* get first param */ + node = cmd_tree->node.kids; + if (node == NULL) { + return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); + } + + if (node->value.s == NULL || node->value.len == 0) { + return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); + } + + /* get module str */ + mod_str = node->value; + + /* get second param */ + node = node->next; + if (node == NULL) { + return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); + } + + if (node->value.s == NULL || node->value.len == 0) { + return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); + } + + /* get facility str */ + facility_str = node->value; + + /* no further params expected */ + node = node->next; + if (node != NULL) { + return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); + } + + /* get facility int */ + facility_str.s[facility_str.len] = '\0'; + if ((fl = str2facility(facility_str.s)) == -1) { + LM_ERR("invalid parameter - facility value: %.*s\n", + facility_str.len, facility_str.s); + return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); + } + + /* set facility int */ + if (default_dbg_cfg.mod_hash_size <= 0 || default_dbg_cfg.mod_facility_mode <= 0 || + dbg_set_mod_debug_facility(mod_str.s, mod_str.len, &fl) < 0) { + LM_ERR("cannot set facility for %.*s; enable mod_hash_size and mod_facility_mode\n", + mod_str.len, mod_str.s); + return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN); + } else { + LM_DBG("module=%.*s facility_str=%.*s facility_int=%d\n", + mod_str.len, mod_str.s, facility_str.len, facility_str.s, fl); + } + + return init_mi_tree(200, MI_OK_S, MI_OK_LEN); +} + + /** * init module function */ @@ -144,6 +274,12 @@ static int mod_init(void) int fl; bind_cfgt_t bind_cfgt; + if (register_mi_mod(exports.name, mi_cmds) != 0) + { + LM_ERR("failed to register MI commands\n"); + return -1; + } + if (_dbg_cfgtrace_facility_str!=NULL) { fl = str2facility(_dbg_cfgtrace_facility_str); From f8a6d4e370bfe95d4968a1c29d275a91cdda12ce Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Tue, 5 Jan 2016 13:24:08 +0200 Subject: [PATCH 078/142] core: add facility2str() function Add support to get the facility number given the facility string. --- dprint.c | 16 +++++++++++++++- dprint.h | 2 ++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/dprint.c b/dprint.c index 0a5c0c3d0ab..269dd837e1e 100644 --- a/dprint.c +++ b/dprint.c @@ -90,13 +90,27 @@ int str2facility(char *s) { int i; - for( i=0; str_fac[i] ; i++) { + for (i=0; str_fac[i]; i++) { if (!strcasecmp(s,str_fac[i])) return int_fac[i]; } return -1; } +char* facility2str(int fl, int *len) +{ + int i; + + for (i=0; str_fac[i]; i++) { + if (fl == int_fac[i]) { + *len = strlen(str_fac[i]); + return str_fac[i]; + } + } + + return NULL; +} + /* fixup function for log_facility cfg parameter */ int log_facility_fixup(void *handle, str *gname, str *name, void **val) { diff --git a/dprint.h b/dprint.h index 35d5a0d4c99..5f03445fef8 100644 --- a/dprint.h +++ b/dprint.h @@ -160,6 +160,8 @@ extern volatile int dprint_crit; #endif int str2facility(char *s); +char* facility2str(int fl, int *len); + int log_facility_fixup(void *handle, str *gname, str *name, void **val); void dprint_color(int level); From 2bd153ce083c81c78b58019cf7acae12646e14e3 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Tue, 29 Dec 2015 17:33:55 +0200 Subject: [PATCH 079/142] debugger: fifo module level/facility getters Add kamctl fifo module level/facility getters. --- modules/debugger/debugger_mod.c | 145 ++++++++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 6 deletions(-) diff --git a/modules/debugger/debugger_mod.c b/modules/debugger/debugger_mod.c index a343bba8cbe..e77982591c2 100644 --- a/modules/debugger/debugger_mod.c +++ b/modules/debugger/debugger_mod.c @@ -66,6 +66,8 @@ extern char* dump_lump_list(struct lump *list, int s_offset, char *s_buf); /* mi commands */ static struct mi_root* mi_set_dbg_mod_level(struct mi_root *cmd_tree, void *param); static struct mi_root* mi_set_dbg_mod_facility(struct mi_root *cmd_tree, void *param); +static struct mi_root* mi_get_dbg_mod_level(struct mi_root *cmd_tree, void *param); +static struct mi_root* mi_get_dbg_mod_facility(struct mi_root *cmd_tree, void *param); /* parameters */ extern int _dbg_cfgtrace; @@ -129,6 +131,8 @@ static param_export_t params[]={ static mi_export_t mi_cmds[] = { {"set_dbg_mod_level", mi_set_dbg_mod_level, 0, 0, 0}, {"set_dbg_mod_facility", mi_set_dbg_mod_facility, 0, 0, 0}, + {"get_dbg_mod_level", mi_get_dbg_mod_level, 0, 0, 0}, + {"get_dbg_mod_facility", mi_get_dbg_mod_facility, 0, 0, 0}, { 0, 0, 0, 0, 0} }; @@ -193,11 +197,13 @@ static struct mi_root* mi_set_dbg_mod_level(struct mi_root *cmd_tree, void *para } /* set level int */ - if (default_dbg_cfg.mod_hash_size <= 0 || default_dbg_cfg.mod_level_mode <= 0 || - dbg_set_mod_debug_level(mod_str.s, mod_str.len, &l) < 0) { - LM_ERR("cannot set level for %.*s; enable mod_hash_size and mod_level_mode\n", + if (default_dbg_cfg.mod_hash_size <= 0 || default_dbg_cfg.mod_level_mode <= 0) { + LM_ERR("can't set level for module=%.*s; enable mod_hash_size and mod_level_mode config parameters!\n", mod_str.len, mod_str.s); return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN); + } else if (dbg_set_mod_debug_level(mod_str.s, mod_str.len, &l) < 0) { + LM_ERR("failed set level for module=%.*s\n", mod_str.len, mod_str.s); + return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN); } else { LM_DBG("module=%.*s level_str=%.*s level_int=%d\n", mod_str.len, mod_str.s, level_str.len, level_str.s, l); @@ -252,11 +258,13 @@ static struct mi_root* mi_set_dbg_mod_facility(struct mi_root *cmd_tree, void *p } /* set facility int */ - if (default_dbg_cfg.mod_hash_size <= 0 || default_dbg_cfg.mod_facility_mode <= 0 || - dbg_set_mod_debug_facility(mod_str.s, mod_str.len, &fl) < 0) { - LM_ERR("cannot set facility for %.*s; enable mod_hash_size and mod_facility_mode\n", + if (default_dbg_cfg.mod_hash_size <= 0 || default_dbg_cfg.mod_facility_mode <= 0) { + LM_ERR("can't set facility for module=%.*s; enable mod_hash_size and mod_facility_mode config parameters!\n", mod_str.len, mod_str.s); return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN); + } else if (dbg_set_mod_debug_facility(mod_str.s, mod_str.len, &fl) < 0) { + LM_ERR("failed set facility for module=%.*s\n", mod_str.len, mod_str.s); + return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN); } else { LM_DBG("module=%.*s facility_str=%.*s facility_int=%d\n", mod_str.len, mod_str.s, facility_str.len, facility_str.s, fl); @@ -265,6 +273,131 @@ static struct mi_root* mi_set_dbg_mod_facility(struct mi_root *cmd_tree, void *p return init_mi_tree(200, MI_OK_S, MI_OK_LEN); } +static struct mi_root* mi_get_dbg_mod_level(struct mi_root *cmd_tree, void *param) { + struct mi_node *node, *crt_node; + struct mi_root *root = NULL; + struct mi_attr *attr; + int l; + str mod_str, level_str; + str level_attr = {"level", strlen("level")}; + + /* get first param */ + node = cmd_tree->node.kids; + if (node == NULL) { + return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); + } + + if (node->value.s == NULL || node->value.len == 0) { + return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); + } + + /* get module str */ + mod_str = node->value; + + /* no further params expected */ + node = node->next; + if (node != NULL) { + return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); + } + + /* get module log level */ + l = get_debug_level(mod_str.s, mod_str.len); + level_str.s = sint2str(l, &level_str.len); + LM_DBG("module=%.*s level_str=%.*s level_int=%d\n", + mod_str.len, mod_str.s, level_str.len, level_str.s, l); + + /* return module log level */ + root = init_mi_tree(200, MI_OK_S, MI_OK_LEN); + if (!root) { + LM_ERR("the MI tree cannot be initialized!\n"); + goto error; + } + node = &root->node; + + if (!(crt_node = add_mi_node_child(node, 0, mod_str.s, mod_str.len, 0, 0)) ) { + LM_ERR("cannot add the child node to the tree\n"); + goto error; + } + + if ((attr = add_mi_attr(crt_node, MI_DUP_VALUE, + level_attr.s, level_attr.len, + level_str.s, level_str.len)) == 0) { + LM_ERR("cannot add attributes to the node\n"); + goto error; + } + + return root; + +error: + if (root) { + free_mi_tree(root); + } + + return NULL; +} + +static struct mi_root* mi_get_dbg_mod_facility(struct mi_root *cmd_tree, void *param) { + struct mi_node *node, *crt_node; + struct mi_root *root = NULL; + struct mi_attr *attr; + int fl; + str mod_str, facility_str; + str facility_attr = {"facility", strlen("facility")}; + + /* get first param */ + node = cmd_tree->node.kids; + if (node == NULL) { + return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); + } + + if (node->value.s == NULL || node->value.len == 0) { + return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); + } + + /* get module str */ + mod_str = node->value; + + /* no further params expected */ + node = node->next; + if (node != NULL) { + return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); + } + + /* get module log facility */ + fl = get_debug_facility(mod_str.s, mod_str.len); + facility_str.s = facility2str(fl, &facility_str.len); + LM_DBG("module=%.*s facility_str=%.*s facility_int=%d\n", + mod_str.len, mod_str.s, facility_str.len, facility_str.s, fl); + + /* return module log facility */ + root = init_mi_tree(200, MI_OK_S, MI_OK_LEN); + if (!root) { + LM_ERR("the MI tree cannot be initialized!\n"); + goto error; + } + node = &root->node; + + if (!(crt_node = add_mi_node_child(node, 0, mod_str.s, mod_str.len, 0, 0)) ) { + LM_ERR("cannot add the child node to the tree\n"); + goto error; + } + + if ((attr = add_mi_attr(crt_node, MI_DUP_VALUE, + facility_attr.s, facility_attr.len, + facility_str.s, facility_str.len)) == 0) { + LM_ERR("cannot add attributes to the node\n"); + goto error; + } + + return root; + +error: + if (root) { + free_mi_tree(root); + } + + return NULL; +} /** * init module function From 70b3dc76a1eac47dc70d5624f27c7f39717ecb7e Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Mon, 4 Jan 2016 11:17:20 +0200 Subject: [PATCH 080/142] debugger: update doku for fifo commands Update doku for fifo commands. --- modules/debugger/doc/debugger_admin.xml | 77 +++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/modules/debugger/doc/debugger_admin.xml b/modules/debugger/doc/debugger_admin.xml index cddfc26746f..0ae70a2f005 100644 --- a/modules/debugger/doc/debugger_admin.xml +++ b/modules/debugger/doc/debugger_admin.xml @@ -616,6 +616,83 @@ P-Hint: My hint
+ +
+ Exported MI Functions + +
+ <function moreinfo="none">set_dbg_mod_level mod_name level</function> + + Set the module log level. + If module does not exist in kamailio, the entry in the level hashtable is still added for the bogus module. + + + <function moreinfo="none">set_dbg_mod_level</function> usage + +... +$ &ctltool; fifo set_dbg_mod_level core 2 +$ &ctltool; fifo set_dbg_mod_level debugger 3 +... + + +
+ +
+ <function moreinfo="none">set_dbg_mod_facility mod_name facility</function> + + Set the mod_name log facility. + If mod_name does not exist in kamailio, the entry in the facility hashtable is still added for the bogus mod_name. + + + <function moreinfo="none">set_dbg_mod_facility</function> usage + +... +$ &ctltool; fifo set_dbg_mod_facility core LOG_LOCAL1 +$ &ctltool; fifo set_dbg_mod_facility debugger LOG_LOCAL0 +... + + +
+ +
+ <function moreinfo="none">get_dbg_mod_level mod_name</function> + + Get the mod_name log level. + If mod_name does not exist in the level hashtable, returns the config file value. + + + <function moreinfo="none">get_dbg_mod_level</function> usage + +... +$ &ctltool; fifo get_dbg_mod_level core +$ &ctltool; fifo get_dbg_mod_level debugger +... + + +
+ +
+ <function moreinfo="none">get_dbg_mod_facility mod_name</function> + + Get the mod_name log facility. + If mod_name does not exist in the facility hashtable, returns the config file value. + + + <function moreinfo="none">get_dbg_mod_facility</function> usage + +... +$ &ctltool; fifo get_dbg_mod_facility core +$ &ctltool; fifo get_dbg_mod_facility debugger +... + + +
+ +
+ + + +
Exported RPC Functions From 33e082dd314a333c62bfbc176a392702cfd9f4cd Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Tue, 5 Jan 2016 11:42:47 +0200 Subject: [PATCH 081/142] debugger: destroy debugger shm hashtable Add a dbg_destroy_mod_levels() functions to be called on mod_destroy(), thus avoiding shm leaks. --- modules/debugger/debugger_api.c | 57 +++++++++++++++++++++++++++++++++ modules/debugger/debugger_api.h | 1 + modules/debugger/debugger_mod.c | 1 + 3 files changed, 59 insertions(+) diff --git a/modules/debugger/debugger_api.c b/modules/debugger/debugger_api.c index 014d5be1640..f060b36acbc 100644 --- a/modules/debugger/debugger_api.c +++ b/modules/debugger/debugger_api.c @@ -1161,6 +1161,63 @@ int dbg_init_mod_levels(int dbg_mod_hash_size) return 0; } +/** + * + */ +int dbg_destroy_mod_levels() +{ + int i; + dbg_mod_level_t *itl = NULL; + dbg_mod_level_t *itlp = NULL; + + dbg_mod_facility_t *itf = NULL; + dbg_mod_facility_t *itfp = NULL; + + if (_dbg_mod_table_size <= 0) + return 0; + + if (_dbg_mod_table == NULL) + return 0; + + for (i = 0; i < _dbg_mod_table_size; i++) { + // destroy level list + lock_get(&_dbg_mod_table[i].lock); + itl = _dbg_mod_table[i].first; + while (itl) { + itlp = itl; + itl = itl->next; + shm_free(itlp); + } + lock_release(&_dbg_mod_table[i].lock); + + // destroy facility list + lock_get(&_dbg_mod_table[i].lock_ft); + itf = _dbg_mod_table[i].first_ft; + while (itf) { + itfp = itf; + itf = itf->next; + shm_free(itfp); + } + lock_release(&_dbg_mod_table[i].lock_ft); + + // destroy locks + lock_destroy(&_dbg_mod_table[i].lock); + lock_destroy(&_dbg_mod_table[i].lock_ft); + + // reset all + _dbg_mod_table[i].first = NULL; + _dbg_mod_table[i].first_ft = NULL; + } + + // free table + shm_free(_dbg_mod_table); + _dbg_mod_table = NULL; + + LM_DBG("Destroyed _dbg_mod_table, size %d\n", _dbg_mod_table_size); + + return 0; +} + /* * case insensitive hashing - clone here to avoid usage of LOG*() * - s1 - str to hash diff --git a/modules/debugger/debugger_api.h b/modules/debugger/debugger_api.h index e41b15ab03f..7d034c27bfd 100644 --- a/modules/debugger/debugger_api.h +++ b/modules/debugger/debugger_api.h @@ -34,6 +34,7 @@ int dbg_init_mypid(void); int dbg_init_rpc(void); int dbg_init_mod_levels(int _dbg_mod_hash_size); +int dbg_destroy_mod_levels(); int dbg_set_mod_debug_level(char *mname, int mnlen, int *mlevel); int dbg_set_mod_debug_facility(char *mname, int mnlen, int *mfacility); void dbg_enable_mod_levels(void); diff --git a/modules/debugger/debugger_mod.c b/modules/debugger/debugger_mod.c index e77982591c2..e37ab83a5f0 100644 --- a/modules/debugger/debugger_mod.c +++ b/modules/debugger/debugger_mod.c @@ -507,6 +507,7 @@ static int child_init(int rank) static void mod_destroy(void) { dbg_cfg = NULL; + dbg_destroy_mod_levels(); } /** From 66943de4344c30fefa361f24213f01f8ef58d2c3 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Tue, 5 Jan 2016 14:02:43 +0200 Subject: [PATCH 082/142] debugger: rpc module level/facility setters Rename kamcmd rpc module level/facility setters. --- modules/debugger/debugger_api.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/debugger/debugger_api.c b/modules/debugger/debugger_api.c index f060b36acbc..0e28b540730 100644 --- a/modules/debugger/debugger_api.c +++ b/modules/debugger/debugger_api.c @@ -981,12 +981,12 @@ static void dbg_rpc_trace(rpc_t* rpc, void* ctx) /** * */ -static const char* dbg_rpc_mod_level_doc[2] = { - "Specify module log level", +static const char* dbg_rpc_set_mod_level_doc[2] = { + "Set module log level", 0 }; -static void dbg_rpc_mod_level(rpc_t* rpc, void* ctx){ +static void dbg_rpc_set_mod_level(rpc_t* rpc, void* ctx){ int l; str value = {0,0}; @@ -1007,12 +1007,12 @@ static void dbg_rpc_mod_level(rpc_t* rpc, void* ctx){ /** * */ -static const char* dbg_rpc_mod_facility_doc[2] = { - "Specify module log facility", +static const char* dbg_rpc_set_mod_facility_doc[2] = { + "Set module log facility", 0 }; -static void dbg_rpc_mod_facility(rpc_t* rpc, void* ctx) { +static void dbg_rpc_set_mod_facility(rpc_t* rpc, void* ctx) { int fl; str value = {0, 0}; str facility = {0, 0}; @@ -1076,8 +1076,8 @@ rpc_export_t dbg_rpc[] = { {"dbg.bp", dbg_rpc_bp, dbg_rpc_bp_doc, 0}, {"dbg.ls", dbg_rpc_list, dbg_rpc_list_doc, 0}, {"dbg.trace", dbg_rpc_trace, dbg_rpc_trace_doc, 0}, - {"dbg.mod_level", dbg_rpc_mod_level, dbg_rpc_mod_level_doc, 0}, - {"dbg.mod_facility", dbg_rpc_mod_facility, dbg_rpc_mod_facility_doc, 0}, + {"dbg.set_mod_level", dbg_rpc_set_mod_level, dbg_rpc_set_mod_level_doc, 0}, + {"dbg.set_mod_facility", dbg_rpc_set_mod_facility, dbg_rpc_set_mod_facility_doc, 0}, {"dbg.reset_msgid", dbg_rpc_reset_msgid, dbg_rpc_reset_msgid_doc, 0}, {0, 0, 0, 0} }; From 144b3c54e4fc23e95e5601e38165defa7c377ba8 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Tue, 5 Jan 2016 14:37:34 +0200 Subject: [PATCH 083/142] debugger: rpc module level/facility getters Add kamcmd rpc module level/facility getters. --- modules/debugger/debugger_api.c | 51 +++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/modules/debugger/debugger_api.c b/modules/debugger/debugger_api.c index 0e28b540730..566be68d491 100644 --- a/modules/debugger/debugger_api.c +++ b/modules/debugger/debugger_api.c @@ -1036,6 +1036,55 @@ static void dbg_rpc_set_mod_facility(rpc_t* rpc, void* ctx) { rpc->add(ctx, "s", "200 ok"); } +/** + * + */ +static const char* dbg_rpc_get_mod_level_doc[2] = { + "Get module log level", + 0 +}; + +static void dbg_rpc_get_mod_level(rpc_t* rpc, void* ctx){ + int l; + str value = {0,0}; + + if (rpc->scan(ctx, "S", &value) < 1) + { + rpc->fault(ctx, 500, "invalid parameters"); + return; + } + + l = get_debug_level(value.s, value.len); + + rpc->add(ctx, "d", l); +} + +/** + * + */ +static const char* dbg_rpc_get_mod_facility_doc[2] = { + "Get module log facility", + 0 +}; + +static void dbg_rpc_get_mod_facility(rpc_t* rpc, void* ctx) { + int fl; + str value = {0, 0}; + str facility = {0, 0}; + + if (rpc->scan(ctx, "S", &value) < 1) + { + rpc->fault(ctx, 500, "invalid parameters"); + return; + } + + fl = get_debug_facility(value.s, value.len); + facility.s = facility2str(fl, &facility.len); + + rpc->add(ctx, "S", &facility); +} + + /** * */ @@ -1078,6 +1127,8 @@ rpc_export_t dbg_rpc[] = { {"dbg.trace", dbg_rpc_trace, dbg_rpc_trace_doc, 0}, {"dbg.set_mod_level", dbg_rpc_set_mod_level, dbg_rpc_set_mod_level_doc, 0}, {"dbg.set_mod_facility", dbg_rpc_set_mod_facility, dbg_rpc_set_mod_facility_doc, 0}, + {"dbg.get_mod_level", dbg_rpc_get_mod_level, dbg_rpc_get_mod_level_doc, 0}, + {"dbg.get_mod_facility", dbg_rpc_get_mod_facility, dbg_rpc_get_mod_facility_doc, 0}, {"dbg.reset_msgid", dbg_rpc_reset_msgid, dbg_rpc_reset_msgid_doc, 0}, {0, 0, 0, 0} }; From 526fb4cdc2246284ecbd7de9ed65678da2dbe357 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 6 Jan 2016 10:03:00 +0100 Subject: [PATCH 084/142] core: added msg_send_buffer() function to allow skipping execution of core events - useful for non-sip messages sent out to skip execution of SREV_NET_DATA_OUT, like HEP packets for sipcapture - msg_send() is now a defined alias for msg_send_buffer() --- forward.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/forward.h b/forward.h index f1418d0507c..9c075b8a067 100644 --- a/forward.h +++ b/forward.h @@ -97,6 +97,7 @@ void forward_set_send_info(int v); int is_check_self_func_list_set(void); +#define msg_send(_dst, _buf, _len) msg_send_buffer((_dst), (_buf), (_len), 0) /* params: * dst = struct dest_info containing: @@ -109,9 +110,12 @@ int is_check_self_func_list_set(void); * (useful for sending replies on the same connection as the request * that generated them; use 0 if you don't want this) * buf, len = buffer + * flags = control internal behavior + * * 1 - skip executing event SREV_NET_DATA_OUT * returns: 0 if ok, -1 on error*/ -static inline int msg_send(struct dest_info* dst, char* buf, int len) +static inline int msg_send_buffer(struct dest_info* dst, char* buf, int len, + int flags) { struct dest_info new_dst; str outb; @@ -127,7 +131,9 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len) outb.s = buf; outb.len = len; - sr_event_exec(SREV_NET_DATA_OUT, (void*)&outb); + if(!(flags&1)) { + sr_event_exec(SREV_NET_DATA_OUT, (void*)&outb); + } if(outb.s==NULL) { LM_ERR("failed to update outgoing buffer\n"); From 284c11ed16bdc5afcc9abf49c9f5c1749ce831e0 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 6 Jan 2016 10:05:35 +0100 Subject: [PATCH 085/142] siptrace: don't execute core event for net data out for HEP packets --- modules/siptrace/siptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/siptrace/siptrace.c b/modules/siptrace/siptrace.c index df6ceff76da..cc0c0f265e7 100644 --- a/modules/siptrace/siptrace.c +++ b/modules/siptrace/siptrace.c @@ -1790,7 +1790,7 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_i memcpy((void*)(buffer + buflen) , (void*)body->s, body->len); buflen +=body->len; - if (msg_send(dst_fin, buffer, buflen)<0) + if (msg_send_buffer(dst_fin, buffer, buflen, 1)<0) { LM_ERR("cannot send hep duplicate message\n"); goto error; From 40c8a62ce85cc14ecf4e30b17d322f9a4177ed8e Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 6 Jan 2016 11:45:33 +0100 Subject: [PATCH 086/142] siptrace: updated the log messages - debug level and function name are added automatically by LM_*() macros --- modules/siptrace/siptrace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/siptrace/siptrace.c b/modules/siptrace/siptrace.c index cc0c0f265e7..7d5c9524453 100644 --- a/modules/siptrace/siptrace.c +++ b/modules/siptrace/siptrace.c @@ -1667,7 +1667,7 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_i /* check if from and to are in the same family*/ if(from_su.s.sa_family != to_su.s.sa_family) { - LOG(L_ERR, "ERROR: trace_send_hep_duplicate: interworking detected ?\n"); + LM_ERR("interworking detected ?\n"); goto error; } @@ -1744,7 +1744,7 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_i len = sizeof(struct hep_ip6hdr); } else { - LOG(L_ERR, "ERROR: trace_send_hep_duplicate: Unsupported protocol family\n"); + LM_ERR("Unsupported protocol family\n"); goto error;; } @@ -1755,7 +1755,7 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_i len += sizeof(struct hep_hdr) + body->len; buffer = (void *)pkg_malloc(len+1); if (buffer==0){ - LOG(L_ERR, "ERROR: trace_send_hep_duplicate: out of memory\n"); + LM_ERR("out of memory\n"); goto error; } From ddb9171c96ef54ceeeb984cb0d9dc6695d206cc6 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 6 Jan 2016 11:47:33 +0100 Subject: [PATCH 087/142] siptrace: coherent indentation --- modules/siptrace/siptrace.c | 245 ++++++++++++++++++------------------ 1 file changed, 122 insertions(+), 123 deletions(-) diff --git a/modules/siptrace/siptrace.c b/modules/siptrace/siptrace.c index 7d5c9524453..158d2f1269d 100644 --- a/modules/siptrace/siptrace.c +++ b/modules/siptrace/siptrace.c @@ -174,7 +174,7 @@ db_func_t db_funcs; /*!< Database functions */ */ static cmd_export_t cmds[] = { {"sip_trace", (cmd_function)sip_trace, 0, 0, 0, ANY_ROUTE}, - {"sip_trace", (cmd_function)sip_trace, 1, fixup_siptrace, 0, ANY_ROUTE}, + {"sip_trace", (cmd_function)sip_trace, 1, fixup_siptrace, 0, ANY_ROUTE}, {0, 0, 0, 0, 0, 0} }; @@ -207,7 +207,7 @@ static param_export_t params[] = { {"xheaders_write", INT_PARAM, &xheaders_write }, {"xheaders_read", INT_PARAM, &xheaders_read }, {"hep_mode_on", INT_PARAM, &hep_mode_on }, - {"force_send_sock", PARAM_STR, &force_send_sock_str }, + {"force_send_sock", PARAM_STR, &force_send_sock_str }, {"hep_version", INT_PARAM, &hep_version }, {"hep_capture_id", INT_PARAM, &hep_capture_id }, {"trace_delayed", INT_PARAM, &trace_delayed }, @@ -297,8 +297,8 @@ static int mod_init(void) *trace_to_database_flag = trace_to_database; if(hep_version != 1 && hep_version != 2) { - LM_ERR("unsupported version of HEP"); - return -1; + LM_ERR("unsupported version of HEP"); + return -1; } /* Find a database module if needed */ @@ -316,12 +316,11 @@ static int mod_init(void) } } - if(hep_version != 1 && hep_version != 2) { - - LM_ERR("unsupported version of HEP"); - return -1; - } + if(hep_version != 1 && hep_version != 2) { + LM_ERR("unsupported version of HEP"); + return -1; + } trace_on_flag = (int*)shm_malloc(sizeof(int)); if(trace_on_flag==NULL) { @@ -391,19 +390,19 @@ static int mod_init(void) if(force_send_sock_str.s!=0) { - force_send_sock_str.len = strlen(force_send_sock_str.s); - force_send_sock_uri = (struct sip_uri *)pkg_malloc(sizeof(struct sip_uri)); - if(force_send_sock_uri==0) - { - LM_ERR("no more pkg memory left\n"); - return -1; - } - memset(force_send_sock_uri, 0, sizeof(struct sip_uri)); - if(parse_uri(force_send_sock_str.s, force_send_sock_str.len, force_send_sock_uri)<0) - { - LM_ERR("bad dup uri\n"); - return -1; - } + force_send_sock_str.len = strlen(force_send_sock_str.s); + force_send_sock_uri = (struct sip_uri *)pkg_malloc(sizeof(struct sip_uri)); + if(force_send_sock_uri==0) + { + LM_ERR("no more pkg memory left\n"); + return -1; + } + memset(force_send_sock_uri, 0, sizeof(struct sip_uri)); + if(parse_uri(force_send_sock_str.s, force_send_sock_str.len, force_send_sock_uri)<0) + { + LM_ERR("bad dup uri\n"); + return -1; + } } if(traced_user_avp_str.s && traced_user_avp_str.len > 0) @@ -466,7 +465,7 @@ static int child_init(int rank) return -1; } if (db_check_table_version(&db_funcs, db_con, &siptrace_table, - SIP_TRACE_TABLE_VERSION) < 0) { + SIP_TRACE_TABLE_VERSION) < 0) { LM_ERR("error during table version check\n"); db_funcs.close(db_con); return -1; @@ -752,7 +751,7 @@ static int sip_trace_store(struct _siptrace_data *sto, struct dest_info *dst) return -1; if(hep_mode_on) trace_send_hep_duplicate(&sto->body, &sto->fromip, &sto->toip, dst); - else trace_send_duplicate(sto->body.s, sto->body.len, dst); + else trace_send_duplicate(sto->body.s, sto->body.len, dst); if (sip_trace_xheaders_free(sto) != 0) return -1; @@ -961,14 +960,14 @@ static int sip_trace(struct sip_msg *msg, struct dest_info * dst, char *dir) struct onsend_info *snd_inf = NULL; if (dst){ - if (dst->send_sock == 0){ - dst->send_sock=get_send_socket(0, &dst->to, dst->proto); - if (dst->send_sock==0){ - LM_ERR("can't forward to af %d, proto %d no corresponding" - " listening socket\n", dst->to.s.sa_family, dst->proto); - return -1; - } - } + if (dst->send_sock == 0){ + dst->send_sock=get_send_socket(0, &dst->to, dst->proto); + if (dst->send_sock==0){ + LM_ERR("can't forward to af %d, proto %d no corresponding" + " listening socket\n", dst->to.s.sa_family, dst->proto); + return -1; + } + } } if(msg==NULL) { @@ -1584,23 +1583,23 @@ static int trace_send_duplicate(char *buf, int len, struct dest_info *dst2) } if (!dst2){ - init_dest_info(&dst); - /* create a temporary proxy*/ - dst.proto = PROTO_UDP; - p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT, - dst.proto); - if (p==0){ - LM_ERR("bad host name in uri\n"); - return -1; - } - hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT); - - dst.send_sock=get_send_socket(0, &dst.to, dst.proto); - if (dst.send_sock==0){ - LM_ERR("can't forward to af %d, proto %d no corresponding" - " listening socket\n", dst.to.s.sa_family, dst.proto); - goto error; - } + init_dest_info(&dst); + /* create a temporary proxy*/ + dst.proto = PROTO_UDP; + p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT, + dst.proto); + if (p==0){ + LM_ERR("bad host name in uri\n"); + return -1; + } + hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT); + + dst.send_sock=get_send_socket(0, &dst.to, dst.proto); + if (dst.send_sock==0){ + LM_ERR("can't forward to af %d, proto %d no corresponding" + " listening socket\n", dst.to.s.sa_family, dst.proto); + goto error; + } } if (msg_send((dst2)?dst2:&dst, buf, len)<0) @@ -1610,15 +1609,15 @@ static int trace_send_duplicate(char *buf, int len, struct dest_info *dst2) } if (p){ - free_proxy(p); /* frees only p content, not p itself */ - pkg_free(p); + free_proxy(p); /* frees only p content, not p itself */ + pkg_free(p); } return 0; error: - if (p){ - free_proxy(p); /* frees only p content, not p itself */ - pkg_free(p); - } + if (p){ + free_proxy(p); /* frees only p content, not p itself */ + pkg_free(p); + } return -1; } @@ -1637,7 +1636,7 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_i struct hep_timehdr hep_time; struct timeval tvb; struct timezone tz; - + struct hep_ip6hdr hep_ip6header; if(body->s==NULL || body->len <= 0) @@ -1647,8 +1646,8 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_i return 0; - gettimeofday( &tvb, &tz ); - + gettimeofday( &tvb, &tz ); + /* message length */ len = body->len @@ -1671,46 +1670,46 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_i goto error; } - if (!dst2){ - init_dest_info(&dst); - /* create a temporary proxy*/ - dst.proto = PROTO_UDP; - p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT, - dst.proto); - if (p==0) - { - LM_ERR("bad host name in uri\n"); - goto error; + if (!dst2){ + init_dest_info(&dst); + /* create a temporary proxy*/ + dst.proto = PROTO_UDP; + p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT, + dst.proto); + if (p==0) + { + LM_ERR("bad host name in uri\n"); + goto error; + } + + hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT); + LM_DBG("setting up the socket_info\n"); + dst_fin = &dst; + } else { + dst_fin = dst2; + } + + if (force_send_sock_str.s) { + LM_DBG("force_send_sock activated, grep for the sock_info\n"); + si = grep_sock_info(&force_send_sock_uri->host, + (force_send_sock_uri->port_no)?force_send_sock_uri->port_no:SIP_PORT, + PROTO_UDP); + if (!si) { + LM_WARN("cannot grep socket info\n"); + } else { + LM_DBG("found socket while grep: [%.*s] [%.*s]\n", si->name.len, si->name.s, si->address_str.len, si->address_str.s); + dst_fin->send_sock = si; + } } - hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT); - LM_DBG("setting up the socket_info\n"); - dst_fin = &dst; - } else { - dst_fin = dst2; - } - - if (force_send_sock_str.s) { - LM_DBG("force_send_sock activated, grep for the sock_info\n"); - si = grep_sock_info(&force_send_sock_uri->host, - (force_send_sock_uri->port_no)?force_send_sock_uri->port_no:SIP_PORT, - PROTO_UDP); - if (!si) { - LM_WARN("cannot grep socket info\n"); - } else { - LM_DBG("found socket while grep: [%.*s] [%.*s]\n", si->name.len, si->name.s, si->address_str.len, si->address_str.s); - dst_fin->send_sock = si; - } - } - - if (dst_fin->send_sock == 0) { - dst_fin->send_sock=get_send_socket(0, &dst_fin->to, dst_fin->proto); - if (dst_fin->send_sock == 0) { - LM_ERR("can't forward to af %d, proto %d no corresponding" - " listening socket\n", dst_fin->to.s.sa_family, dst_fin->proto); - goto error; - } - } + if (dst_fin->send_sock == 0) { + dst_fin->send_sock=get_send_socket(0, &dst_fin->to, dst_fin->proto); + if (dst_fin->send_sock == 0) { + LM_ERR("can't forward to af %d, proto %d no corresponding" + " listening socket\n", dst_fin->to.s.sa_family, dst_fin->proto); + goto error; + } + } /* Version && proto && length */ hdr.hp_l = sizeof(struct hep_hdr); @@ -1778,13 +1777,13 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_i if(hep_version == 2) { - hep_time.tv_sec = tvb.tv_sec; - hep_time.tv_usec = tvb.tv_usec; - hep_time.captid = hep_capture_id; + hep_time.tv_sec = tvb.tv_sec; + hep_time.tv_usec = tvb.tv_usec; + hep_time.captid = hep_capture_id; - memcpy((void*)buffer+buflen, &hep_time, sizeof(struct hep_timehdr)); - buflen += sizeof(struct hep_timehdr); - } + memcpy((void*)buffer+buflen, &hep_time, sizeof(struct hep_timehdr)); + buflen += sizeof(struct hep_timehdr); + } /* PAYLOAD */ memcpy((void*)(buffer + buflen) , (void*)body->s, body->len); @@ -1796,10 +1795,10 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_i goto error; } - if (p) { - free_proxy(p); /* frees only p content, not p itself */ - pkg_free(p); - } + if (p) { + free_proxy(p); /* frees only p content, not p itself */ + pkg_free(p); + } pkg_free(buffer); return 0; error: @@ -1843,14 +1842,14 @@ static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int LM_ERR("bad protocol %s\n", pipport); return -1; } - + if((len = strlen(pipport)) >= 256) { LM_ERR("too big pipport\n"); goto error; } /* our tmp string */ - strncpy(tmp_piport, pipport, len+1); + strncpy(tmp_piport, pipport, len+1); len = 0; @@ -1867,19 +1866,19 @@ static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int port_no = 0; } else { - /*the address contains a port number*/ - *p = '\0'; - p++; - port_str.s = p; - port_str.len = strlen(p); - LM_DBG("the port string is %s\n", p); - if(str2int(&port_str, &port_no) != 0 ) { - LM_ERR("there is not a valid number port\n"); - goto error; - } - *p = '\0'; - } - + /*the address contains a port number*/ + *p = '\0'; + p++; + port_str.s = p; + port_str.len = strlen(p); + LM_DBG("the port string is %s\n", p); + if(str2int(&port_str, &port_no) != 0 ) { + LM_ERR("there is not a valid number port\n"); + goto error; + } + *p = '\0'; + } + /* now IPv6 address has no brakets. It should be fixed! */ if (host_s[0] == '[') { len = strlen(host_s + 1) - 1; @@ -1939,8 +1938,8 @@ static void siptrace_rpc_status (rpc_t* rpc, void* c) { } static const char* siptrace_status_doc[2] = { - "Get status or turn on/off siptrace. Parameters: on, off or check.", - 0 + "Get status or turn on/off siptrace. Parameters: on, off or check.", + 0 }; rpc_export_t siptrace_rpc[] = { From fa0517f83a09625d14ec0dd3f349a1033f274f86 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Wed, 6 Jan 2016 14:06:07 +0200 Subject: [PATCH 088/142] debugger: update doku for rpc commands Update doku for rpc commands. --- modules/debugger/doc/debugger_admin.xml | 78 +++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/modules/debugger/doc/debugger_admin.xml b/modules/debugger/doc/debugger_admin.xml index 0ae70a2f005..04ba4ee977c 100644 --- a/modules/debugger/doc/debugger_admin.xml +++ b/modules/debugger/doc/debugger_admin.xml @@ -874,7 +874,85 @@ $ &ctltool; fifo get_dbg_mod_facility debugger
+
+ + <function moreinfo="none">dbg.set_mod_level</function> + + + Set the module log level. + If module does not exist in kamailio, the entry in the level hashtable is still added for the bogus module. + + + Name: dbg.set_mod_level + + + Examples of use with &sercmd;: + + + dbg.set_mod_level core 1 + +
+ +
+ + <function moreinfo="none">dbg.set_mod_facility</function> + + + Set the module log facility. + If module does not exist in kamailio, the entry in the facility hashtable is still added for the bogus module. + + + Name: dbg.set_mod_facility + + + Examples of use with &sercmd;: + + + dbg.set_mod_facility core LOG_LOCAL1 + +
+ +
+ + <function moreinfo="none">dbg.get_mod_level</function> + + + Get the module log level. + If module does not exist in kamailio, the entry in the level hashtable is still added for the bogus module. + + + Name: dbg.get_mod_level + + + Examples of use with &sercmd;: + + + dbg.get_mod_level core + +
+ +
+ + <function moreinfo="none">dbg.get_mod_facility</function> + + + Get the module log facility. + If module does not exist in kamailio, the entry in the facility hashtable is still added for the bogus module. + + + Name: dbg.get_mod_facility + + + Examples of use with &sercmd;: + + + dbg.get_mod_facility core + +
+
+ +
Usage From 3668618369a8a1db8cb3410c0a7f50ce74150cd2 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Thu, 7 Jan 2016 09:58:42 +0200 Subject: [PATCH 089/142] debugger: fix issue #463 Don't shm_malloc() while the lock is taken. --- modules/debugger/debugger_api.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/debugger/debugger_api.c b/modules/debugger/debugger_api.c index 566be68d491..cb57df315c4 100644 --- a/modules/debugger/debugger_api.c +++ b/modules/debugger/debugger_api.c @@ -1344,15 +1344,14 @@ int dbg_set_mod_debug_level(char *mname, int mnlen, int *mlevel) itp = it; it = it->next; } + lock_release(&_dbg_mod_table[idx].lock); /* not found - add */ if(mlevel==NULL) { - lock_release(&_dbg_mod_table[idx].lock); return 0; } itn = (dbg_mod_level_t*)shm_malloc(sizeof(dbg_mod_level_t) + (mnlen+1)*sizeof(char)); if(itn==NULL) { LM_ERR("no more shm\n"); - lock_release(&_dbg_mod_table[idx].lock); return -1; } memset(itn, 0, sizeof(dbg_mod_level_t) + (mnlen+1)*sizeof(char)); @@ -1363,6 +1362,7 @@ int dbg_set_mod_debug_level(char *mname, int mnlen, int *mlevel) strncpy(itn->name.s, mname, mnlen); itn->name.s[itn->name.len] = '\0'; + lock_get(&_dbg_mod_table[idx].lock); if(itp==NULL) { itn->next = _dbg_mod_table[idx].first; _dbg_mod_table[idx].first = itn; @@ -1420,15 +1420,14 @@ int dbg_set_mod_debug_facility(char *mname, int mnlen, int *mfacility) itp = it; it = it->next; } + lock_release(&_dbg_mod_table[idx].lock_ft); /* not found - add */ if(mfacility==NULL) { - lock_release(&_dbg_mod_table[idx].lock_ft); return 0; } itn = (dbg_mod_facility_t*)shm_malloc(sizeof(dbg_mod_facility_t) + (mnlen+1)*sizeof(char)); if(itn==NULL) { LM_ERR("no more shm\n"); - lock_release(&_dbg_mod_table[idx].lock_ft); return -1; } memset(itn, 0, sizeof(dbg_mod_facility_t) + (mnlen+1)*sizeof(char)); @@ -1439,6 +1438,7 @@ int dbg_set_mod_debug_facility(char *mname, int mnlen, int *mfacility) strncpy(itn->name.s, mname, mnlen); itn->name.s[itn->name.len] = '\0'; + lock_get(&_dbg_mod_table[idx].lock_ft); if(itp==NULL) { itn->next = _dbg_mod_table[idx].first_ft; _dbg_mod_table[idx].first_ft = itn; From a372f861f04b04f08d68f28a95f12a13776be891 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Thu, 7 Jan 2016 10:32:37 +0200 Subject: [PATCH 090/142] debugger: doku dbg.get_mod_* Overlooked due to copy/paste. --- modules/debugger/doc/debugger_admin.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/debugger/doc/debugger_admin.xml b/modules/debugger/doc/debugger_admin.xml index 04ba4ee977c..d0f3511c0cb 100644 --- a/modules/debugger/doc/debugger_admin.xml +++ b/modules/debugger/doc/debugger_admin.xml @@ -918,7 +918,7 @@ $ &ctltool; fifo get_dbg_mod_facility debugger Get the module log level. - If module does not exist in kamailio, the entry in the level hashtable is still added for the bogus module. + If mod_name does not exist in the level hashtable, returns the config file value. Name: dbg.get_mod_level @@ -937,7 +937,7 @@ $ &ctltool; fifo get_dbg_mod_facility debugger Get the module log facility. - If module does not exist in kamailio, the entry in the facility hashtable is still added for the bogus module. + If mod_name does not exist in the facility hashtable, returns the config file value. Name: dbg.get_mod_facility From c46a5f2792b8553ade871d98cfe892c5a48a3ff6 Mon Sep 17 00:00:00 2001 From: Ian Yu-Hsun Lin Date: Thu, 7 Jan 2016 19:10:51 +0800 Subject: [PATCH 091/142] registrar: do make use of reg_xavp_cfg - prevent from resetting sock_flag to -1 when reg_xavp_cfg is set --- modules/registrar/reg_mod.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/registrar/reg_mod.c b/modules/registrar/reg_mod.c index 98b136b299c..0d7c5acf0f7 100644 --- a/modules/registrar/reg_mod.c +++ b/modules/registrar/reg_mod.c @@ -362,8 +362,14 @@ static int mod_init(void) sock_hdr_name.len = 0; sock_flag = -1; } + } else if (reg_xavp_cfg.s) { + if (reg_xavp_cfg.len == 0 || sock_flag == -1) { + LM_WARN("empty reg_xavp_cfg or sock_flag no set -> resetting\n"); + reg_xavp_cfg.len = 0; + sock_flag = -1; + } } else if (sock_flag!=-1) { - LM_WARN("sock_flag defined but no sock_hdr_name -> reseting flag\n"); + LM_WARN("sock_flag defined but no sock_hdr_name or no reg_xavp_cfg -> resetting flag\n"); sock_flag = -1; } From 53263a2ddad9bb118763516bcd7995652c4fb070 Mon Sep 17 00:00:00 2001 From: Hugh Waite Date: Thu, 7 Jan 2016 12:17:03 +0000 Subject: [PATCH 092/142] tm: Reset socket variable while forking - Reset sock_str variable so values from previous forks are not stored in contact_flows AVP --- modules/tm/t_serial.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/tm/t_serial.c b/modules/tm/t_serial.c index b278924f009..2fb734f23ec 100644 --- a/modules/tm/t_serial.c +++ b/modules/tm/t_serial.c @@ -626,6 +626,8 @@ int t_next_contacts(struct sip_msg* msg, char* key, char* value) } } else { sock = NULL; + sock_str.s = 0; + sock_str.len = 0; } vavp = xavp_get(&flags_name, xavp->val.v.xavp); From 46d3a3ef2314f3177d64beab466401104d3ff887 Mon Sep 17 00:00:00 2001 From: lazedo Date: Fri, 8 Jan 2016 02:52:04 +0000 Subject: [PATCH 093/142] db_text: fix bug in raw query where clause wrong type was allocated --- modules/db_text/dbt_raw_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/db_text/dbt_raw_util.c b/modules/db_text/dbt_raw_util.c index ffbfa3b5ad9..9b0e2d7e74b 100644 --- a/modules/db_text/dbt_raw_util.c +++ b/modules/db_text/dbt_raw_util.c @@ -216,7 +216,7 @@ int dbt_build_where(char* where, db_key_t** _k, db_op_t** _o, db_val_t** _v) // needs changes in dbt_query / dbt_row_match l = matches[2].rm_eo - matches[2].rm_so; - _k1[idx] = pkg_malloc(sizeof(db_key_t)); + _k1[idx] = pkg_malloc(sizeof(str)); _k1[idx]->len = l; _k1[idx]->s = pkg_malloc(sizeof(char) * (l+1)); strncpy(_k1[idx]->s, buffer+matches[2].rm_so, l); From 59ce55977e91c399b86177060421d32dbbd7be06 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jan 2016 11:37:07 +0100 Subject: [PATCH 094/142] tls: more details about tls.cfg reload --- modules/tls/doc/rpc.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/tls/doc/rpc.xml b/modules/tls/doc/rpc.xml index 5efbdee602d..48b7f6a41a1 100644 --- a/modules/tls/doc/rpc.xml +++ b/modules/tls/doc/rpc.xml @@ -53,8 +53,10 @@
<function>tls.reload</function> - Reload the external TLS configuration file. (Does not reload - modparam() parameters) + Reload the external TLS configuration file (aka tls.cfg). It does not reload + modparam() parameters. Note that existing active TLS connections are not + terminated and they continue to use the old certificates. New configuration + will be used for new connections. Parameters: From 8b3847085e793596528d4675acce467a2e7629b7 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jan 2016 11:37:29 +0100 Subject: [PATCH 095/142] tls: regenerated the readme file --- modules/tls/README | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/tls/README b/modules/tls/README index e68449895c0..da740773dd0 100644 --- a/modules/tls/README +++ b/modules/tls/README @@ -1306,8 +1306,10 @@ modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg") 11.4. tls.reload - Reload the external TLS configuration file. (Does not reload modparam() - parameters) + Reload the external TLS configuration file (aka tls.cfg). It does not + reload modparam() parameters. Note that existing active TLS connections + are not terminated and they continue to use the old certificates. New + configuration will be used for new connections. Parameters: * None. From 1f00d722aaefbd2515ae69ffdcf541143862d9fd Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jan 2016 12:39:59 +0100 Subject: [PATCH 096/142] core: new event SREV_NET_DATA_SEND - to be executed if message was sent to the network --- events.c | 13 +++++++++++++ events.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/events.c b/events.c index bb1373afcc2..b140b615a7b 100644 --- a/events.c +++ b/events.c @@ -170,6 +170,11 @@ int sr_event_register_cb(int type, sr_event_cb_f f) _sr_events_list.tcp_closed = f; else return -1; break; + case SREV_NET_DATA_SEND: + if(_sr_events_list.net_data_send==0) + _sr_events_list.net_data_send = f; + else return -1; + break; default: return -1; } @@ -295,6 +300,12 @@ int sr_event_exec(int type, void *data) ret = _sr_events_list.tcp_closed(data); return ret; } else return 1; + case SREV_NET_DATA_SEND: + if(unlikely(_sr_events_list.net_data_send!=0)) + { + ret = _sr_events_list.net_data_send(data); + return ret; + } else return 1; default: return -1; } @@ -332,6 +343,8 @@ int sr_event_enabled(int type) return (_sr_events_list.rcv_nosip!=0)?1:0; case SREV_TCP_CLOSED: return (_sr_events_list.tcp_closed!=0)?1:0; + case SREV_NET_DATA_SEND: + return (_sr_events_list.net_data_send!=0)?1:0; } return 0; } diff --git a/events.h b/events.h index 2946d940ecc..86ab7844fdd 100644 --- a/events.h +++ b/events.h @@ -35,6 +35,7 @@ #define SREV_TCP_WS_FRAME_OUT 11 #define SREV_STUN_IN 12 #define SREV_TCP_CLOSED 13 +#define SREV_NET_DATA_SEND 14 #define SREV_CB_LIST_SIZE 3 @@ -54,6 +55,7 @@ typedef struct sr_event_cb { sr_event_cb_f stun_in; sr_event_cb_f rcv_nosip; sr_event_cb_f tcp_closed; + sr_event_cb_f net_data_send; } sr_event_cb_t; void sr_event_cb_init(void); From 53529269d88adf140985192cd4ba6e8174fcc231 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jan 2016 12:40:59 +0100 Subject: [PATCH 097/142] core: execute event SREV_NET_DATA_SEND if data was sent to network --- forward.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/forward.h b/forward.h index 9c075b8a067..537d378fae2 100644 --- a/forward.h +++ b/forward.h @@ -56,6 +56,11 @@ enum ss_mismatch { SS_MISMATCH_MCAST /* mcast forced send socket */ }; +typedef struct sr_send_info { + str data; + struct dest_info* dst; +} sr_net_info_t; + struct socket_info* get_send_socket2(struct socket_info* force_send_socket, union sockaddr_union* su, int proto, enum ss_mismatch* mismatch); @@ -119,6 +124,8 @@ static inline int msg_send_buffer(struct dest_info* dst, char* buf, int len, { struct dest_info new_dst; str outb; + sr_net_info_t netinfo; + #ifdef USE_TCP int port; struct ip_addr ip; @@ -271,6 +278,15 @@ static inline int msg_send_buffer(struct dest_info* dst, char* buf, int len, } ret = 0; done: + + if(!(flags&1)) { + memset(&netinfo, 0, sizeof(sr_net_info_t)); + netinfo.data.s = outb.s; + netinfo.data.len = outb.len; + netinfo.dst = dst; + sr_event_exec(SREV_NET_DATA_SEND, (void*)&netinfo); + } + if(outb.s != buf) pkg_free(outb.s); return ret; From 1771f7e489b060290b38fc0a428058ca7e2b5f42 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jan 2016 12:41:48 +0100 Subject: [PATCH 098/142] siptrace: new parameter trace_mode - if set to 1, is using the SREV_NET_DATA_SEND event for sending HEP packets to sipcapture server for packets sent to the network --- modules/siptrace/siptrace.c | 56 ++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/modules/siptrace/siptrace.c b/modules/siptrace/siptrace.c index 158d2f1269d..7c689c3cef8 100644 --- a/modules/siptrace/siptrace.c +++ b/modules/siptrace/siptrace.c @@ -50,6 +50,7 @@ #include "../../modules/sl/sl.h" #include "../../str.h" #include "../../onsend.h" +#include "../../events.h" #include "../../modules/sipcapture/hep.h" @@ -106,6 +107,9 @@ static void trace_sl_ack_in(sl_cbp_t *slcb); static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info*); static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int *proto); +int siptrace_net_data_send(void *data); +static int _siptrace_mode = 0; + static struct mi_root* sip_trace_mi(struct mi_root* cmd, void* param ); @@ -211,6 +215,7 @@ static param_export_t params[] = { {"hep_version", INT_PARAM, &hep_version }, {"hep_capture_id", INT_PARAM, &hep_capture_id }, {"trace_delayed", INT_PARAM, &trace_delayed }, + {"trace_mode", PARAM_INT, &_siptrace_mode }, {0, 0, 0} }; @@ -448,6 +453,9 @@ static int mod_init(void) trace_table_avp_type = 0; } + if(_siptrace_mode==1) { + sr_event_register_cb(SREV_NET_DATA_SEND, siptrace_net_data_send); + } return 0; } @@ -1906,6 +1914,53 @@ static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int return -1; } +/** + * + */ +int siptrace_net_data_send(void *data) +{ + sr_net_info_t *nd; + struct dest_info new_dst; + struct _siptrace_data sto; + + if(data==0) + return -1; + + nd = (sr_net_info_t*)data; + if(nd->dst==NULL || nd->data.s==NULL || nd->data.len<=0) + return -1; + + new_dst=*nd->dst; + new_dst.send_sock=get_send_socket(0, &nd->dst->to, nd->dst->proto); + + memset(&sto, 0, sizeof(struct _siptrace_data)); + + sto.body.s = nd->data.s; + sto.body.len = nd->data.len; + + if (unlikely(new_dst.send_sock==0)) { + LM_WARN("no sending socket found\n"); + strcpy(sto.fromip_buff, "any:255.255.255.255:5060"); + } else { + strncpy(sto.fromip_buff, new_dst.send_sock->sock_str.s, + new_dst.send_sock->sock_str.len); + } + sto.fromip.s = sto.fromip_buff; + sto.fromip.len = strlen(sto.fromip_buff); + + siptrace_copy_proto(new_dst.send_sock->proto, sto.toip_buff); + strcat(sto.toip_buff, suip2a(&new_dst.to, sizeof(new_dst.to))); + strcat(sto.toip_buff,":"); + strcat(sto.toip_buff, int2str((int)su_getport(&new_dst.to), NULL)); + sto.toip.s = sto.toip_buff; + sto.toip.len = strlen(sto.toip_buff); + + sto.dir = "out"; + + trace_send_hep_duplicate(&sto.body, &sto.fromip, &sto.toip, NULL); + return 0; +} + static void siptrace_rpc_status (rpc_t* rpc, void* c) { str status = {0, 0}; @@ -1956,4 +2011,3 @@ static int siptrace_init_rpc(void) } return 0; } - From 581912f5ed117bb56087668aa7ac60a7b667d525 Mon Sep 17 00:00:00 2001 From: Carsten Bock Date: Mon, 11 Jan 2016 15:14:37 +0100 Subject: [PATCH 099/142] ims_charging: Properly check final_unit_action-flag for initial requests If final_unit_action flag is set in initial ccr response, kamailio need to send terminate request after the granted time instead of sending an CCR-UPDATE request. Patch by DileepNunna Closes Github #467 (Kamailio sending update ccr request instead of terminate request for initial ccr response having final_unit_action flag) --- modules/ims_charging/ims_ro.c | 4 ++++ modules/ims_charging/ro_session_hash.h | 1 + modules/ims_charging/ro_timer.c | 13 +++++++++++++ 3 files changed, 18 insertions(+) diff --git a/modules/ims_charging/ims_ro.c b/modules/ims_charging/ims_ro.c index adb536ddd87..88647887943 100644 --- a/modules/ims_charging/ims_ro.c +++ b/modules/ims_charging/ims_ro.c @@ -1255,6 +1255,10 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca, ssd->ro_session->event_type = pending; ssd->ro_session->reserved_secs = ro_cca_data->mscc->granted_service_unit->cc_time; ssd->ro_session->valid_for = ro_cca_data->mscc->validity_time; + ssd->ro_session->is_final_allocation = 0; + + if (ro_cca_data->mscc->final_unit_action && (ro_cca_data->mscc->final_unit_action->action == 0)) + ssd->ro_session->is_final_allocation = 1; Ro_free_CCA(ro_cca_data); diff --git a/modules/ims_charging/ro_session_hash.h b/modules/ims_charging/ro_session_hash.h index 7aa1b89bdb4..fa92ed96e3a 100644 --- a/modules/ims_charging/ro_session_hash.h +++ b/modules/ims_charging/ro_session_hash.h @@ -71,6 +71,7 @@ struct ro_session { str mac; int rating_group; int service_identifier; + unsigned int is_final_allocation; }; /*! entries in the main ro_session table */ diff --git a/modules/ims_charging/ro_timer.c b/modules/ims_charging/ro_timer.c index f5978d6da6a..40f3c4240fb 100644 --- a/modules/ims_charging/ro_timer.c +++ b/modules/ims_charging/ro_timer.c @@ -400,6 +400,19 @@ void ro_session_ontimeout(struct ro_tl *tl) { // return; // } + + if(ro_session->is_final_allocation) { + now = get_current_time_micro(); + used_secs = now - ro_session->last_event_timestamp; + if((ro_session->reserved_secs - used_secs) > 0) { + update_ro_timer(&ro_session->ro_tl, (ro_session->reserved_secs - used_secs)); + return; + } + else { + ro_session->event_type = no_more_credit; + } + } + switch (ro_session->event_type) { case answered: now = get_current_time_micro(); From b57a2d7815ad374ba799af4b02c3bccd7942d539 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jan 2016 22:20:43 +0100 Subject: [PATCH 100/142] core: relocated sr_net_info_t struct for availability --- forward.h | 4 ---- ip_addr.h | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/forward.h b/forward.h index 537d378fae2..9c152360a89 100644 --- a/forward.h +++ b/forward.h @@ -56,10 +56,6 @@ enum ss_mismatch { SS_MISMATCH_MCAST /* mcast forced send socket */ }; -typedef struct sr_send_info { - str data; - struct dest_info* dst; -} sr_net_info_t; struct socket_info* get_send_socket2(struct socket_info* force_send_socket, union sockaddr_union* su, int proto, diff --git a/ip_addr.h b/ip_addr.h index 20176b09dd1..c2b724cab51 100644 --- a/ip_addr.h +++ b/ip_addr.h @@ -136,6 +136,11 @@ struct receive_info{ /* no need for dst_su yet */ }; +typedef struct sr_net_info { + str data; + struct dest_info* dst; + struct receive_info* rcv; +} sr_net_info_t; /* send flags */ #define SND_F_FORCE_CON_REUSE 1 /* reuse an existing connection or fail */ From 34afdb987d55d984da49b5896649cea1fc3d075b Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jan 2016 22:21:37 +0100 Subject: [PATCH 101/142] core: new event SREV_NET_DATA_RECV - to be executed if a sip message has been received --- events.c | 13 +++++++++++++ events.h | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/events.c b/events.c index b140b615a7b..d2e32863519 100644 --- a/events.c +++ b/events.c @@ -170,6 +170,11 @@ int sr_event_register_cb(int type, sr_event_cb_f f) _sr_events_list.tcp_closed = f; else return -1; break; + case SREV_NET_DATA_RECV: + if(_sr_events_list.net_data_recv==0) + _sr_events_list.net_data_recv = f; + else return -1; + break; case SREV_NET_DATA_SEND: if(_sr_events_list.net_data_send==0) _sr_events_list.net_data_send = f; @@ -300,6 +305,12 @@ int sr_event_exec(int type, void *data) ret = _sr_events_list.tcp_closed(data); return ret; } else return 1; + case SREV_NET_DATA_RECV: + if(unlikely(_sr_events_list.net_data_recv!=0)) + { + ret = _sr_events_list.net_data_recv(data); + return ret; + } else return 1; case SREV_NET_DATA_SEND: if(unlikely(_sr_events_list.net_data_send!=0)) { @@ -343,6 +354,8 @@ int sr_event_enabled(int type) return (_sr_events_list.rcv_nosip!=0)?1:0; case SREV_TCP_CLOSED: return (_sr_events_list.tcp_closed!=0)?1:0; + case SREV_NET_DATA_RECV: + return (_sr_events_list.net_data_recv!=0)?1:0; case SREV_NET_DATA_SEND: return (_sr_events_list.net_data_send!=0)?1:0; } diff --git a/events.h b/events.h index 86ab7844fdd..60d53d7c4ac 100644 --- a/events.h +++ b/events.h @@ -35,7 +35,8 @@ #define SREV_TCP_WS_FRAME_OUT 11 #define SREV_STUN_IN 12 #define SREV_TCP_CLOSED 13 -#define SREV_NET_DATA_SEND 14 +#define SREV_NET_DATA_RECV 14 +#define SREV_NET_DATA_SEND 15 #define SREV_CB_LIST_SIZE 3 @@ -55,6 +56,7 @@ typedef struct sr_event_cb { sr_event_cb_f stun_in; sr_event_cb_f rcv_nosip; sr_event_cb_f tcp_closed; + sr_event_cb_f net_data_recv; sr_event_cb_f net_data_send; } sr_event_cb_t; From 4fc969760d8eec6355ce661ccd3c5fd9ad2a36f0 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jan 2016 22:23:26 +0100 Subject: [PATCH 102/142] core: execute SREV_NET_DATA_RECV event --- receive.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/receive.c b/receive.c index 8a633cd18ee..a9e1fc3c075 100644 --- a/receive.c +++ b/receive.c @@ -91,6 +91,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) unsigned int diff; #endif str inb; + sr_net_info_t netinfo; inb.s = buf; inb.len = len; @@ -139,6 +140,14 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) /* ... clear branches from previous message */ clear_branches(); + if(sr_event_enabled(SREV_NET_DATA_RECV)) { + memset(&netinfo, 0, sizeof(sr_net_info_t)); + netinfo.data.s = msg->buf; + netinfo.data.len = msg->len; + netinfo.rcv = rcv_info; + sr_event_exec(SREV_NET_DATA_RECV, (void*)&netinfo); + } + if (msg->first_line.type==SIP_REQUEST){ ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */ if (!IS_SIP(msg)){ From 57e7b28bd811971f16154cee08acc2d2024dee76 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jan 2016 22:23:48 +0100 Subject: [PATCH 103/142] siptrace: use SREV_NET_DATA_RECV event for incoming traffic with trace_mode=1 --- modules/siptrace/siptrace.c | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/modules/siptrace/siptrace.c b/modules/siptrace/siptrace.c index 7c689c3cef8..613ea31f1f3 100644 --- a/modules/siptrace/siptrace.c +++ b/modules/siptrace/siptrace.c @@ -107,6 +107,7 @@ static void trace_sl_ack_in(sl_cbp_t *slcb); static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info*); static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int *proto); +int siptrace_net_data_recv(void *data); int siptrace_net_data_send(void *data); static int _siptrace_mode = 0; @@ -454,6 +455,7 @@ static int mod_init(void) } if(_siptrace_mode==1) { + sr_event_register_cb(SREV_NET_DATA_RECV, siptrace_net_data_recv); sr_event_register_cb(SREV_NET_DATA_SEND, siptrace_net_data_send); } return 0; @@ -1914,6 +1916,48 @@ static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int return -1; } + +/** + * + */ +int siptrace_net_data_recv(void *data) +{ + sr_net_info_t *nd; + struct _siptrace_data sto; + + if(data==0) + return -1; + + nd = (sr_net_info_t*)data; + if(nd->rcv==NULL || nd->data.s==NULL || nd->data.len<=0) + return -1; + + memset(&sto, 0, sizeof(struct _siptrace_data)); + + sto.body.s = nd->data.s; + sto.body.len = nd->data.len; + + siptrace_copy_proto(nd->rcv->proto, sto.fromip_buff); + strcat(sto.fromip_buff, ip_addr2a(&nd->rcv->src_ip)); + strcat(sto.fromip_buff,":"); + strcat(sto.fromip_buff, int2str(nd->rcv->src_port, NULL)); + sto.fromip.s = sto.fromip_buff; + sto.fromip.len = strlen(sto.fromip_buff); + + siptrace_copy_proto(nd->rcv->proto, sto.toip_buff); + strcat(sto.toip_buff, ip_addr2a(&nd->rcv->dst_ip)); + strcat(sto.toip_buff,":"); + strcat(sto.toip_buff, int2str(nd->rcv->dst_port, NULL)); + sto.toip.s = sto.toip_buff; + sto.toip.len = strlen(sto.toip_buff); + + sto.dir = "in"; + + trace_send_hep_duplicate(&sto.body, &sto.fromip, &sto.toip, NULL); + return 0; + +} + /** * */ From 2d2c0bec3170b3ef6c10dc9a3b9e990b8d50e0bc Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jan 2016 22:30:09 +0100 Subject: [PATCH 104/142] siptrace: documented trace_mode parameter --- modules/siptrace/doc/siptrace_admin.xml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/modules/siptrace/doc/siptrace_admin.xml b/modules/siptrace/doc/siptrace_admin.xml index c76653136b9..7c454f71304 100644 --- a/modules/siptrace/doc/siptrace_admin.xml +++ b/modules/siptrace/doc/siptrace_admin.xml @@ -466,6 +466,30 @@ modparam("siptrace", "trace_delayed", 1) ... modparam("siptrace", "force_send_sock", "sip:10.1.1.2:5000") ... + + +
+
+ <varname>trace_mode</varname> (integer) + + If set to 1, the module uses core events triggered when receiving + or sending SIP traffic to mirror traffic to a SIP capture server + using HEP. It will automatically do the mirroring of all traffic, + no need to set the siptrace flag per request. + + + If set to 0, no automatic mirroring of SIP traffic via HEP. + + + Default value is 0. + + + Set <varname>trace_mode</varname> + parameter + +... +modparam("siptrace", "trace_mode", 1) +...
From 142fb5a289a6ff4b0cc631293f7acbb65414e889 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jan 2016 22:31:20 +0100 Subject: [PATCH 105/142] siptrace: readme regenerated --- modules/siptrace/README | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/modules/siptrace/README b/modules/siptrace/README index 5dfa7a76691..7ee26f96325 100644 --- a/modules/siptrace/README +++ b/modules/siptrace/README @@ -16,9 +16,9 @@ Daniel-Constantin Mierla - Copyright (c) 2010 asipto.com + Copyright © 2010 asipto.com - Copyright (c) 2006 voice-system.ro + Copyright © 2006 voice-system.ro __________________________________________________________________ Table of Contents @@ -50,6 +50,7 @@ Daniel-Constantin Mierla 3.15. hep_capture_id (integer) 3.16. trace_delayed (integer) 3.17. force_send_sock (str) + 3.18. trace_mode (integer) 4. Functions @@ -85,7 +86,8 @@ Daniel-Constantin Mierla 1.15. Set hep_capture_id parameter 1.16. Set trace_delayed parameter 1.17. Set force_send_sock parameter - 1.18. sip_trace() usage + 1.18. Set trace_mode parameter + 1.19. sip_trace() usage Chapter 1. Admin Guide @@ -116,6 +118,7 @@ Chapter 1. Admin Guide 3.15. hep_capture_id (integer) 3.16. trace_delayed (integer) 3.17. force_send_sock (str) + 3.18. trace_mode (integer) 4. Functions @@ -190,6 +193,7 @@ Chapter 1. Admin Guide 3.15. hep_capture_id (integer) 3.16. trace_delayed (integer) 3.17. force_send_sock (str) + 3.18. trace_mode (integer) 3.1. db_url (str) @@ -420,11 +424,27 @@ modparam("siptrace", "trace_delayed", 1) modparam("siptrace", "force_send_sock", "sip:10.1.1.2:5000") ... +3.18. trace_mode (integer) + + If set to 1, the module uses core events triggered when receiving or + sending SIP traffic to mirror traffic to a SIP capture server using + HEP. It will automatically do the mirroring of all traffic, no need to + set the siptrace flag per request. + + If set to 0, no automatic mirroring of SIP traffic via HEP. + + Default value is 0. + + Example 1.18. Set trace_mode parameter +... +modparam("siptrace", "trace_mode", 1) +... + 4. Functions 4.1. sip_trace([address]) -4.1. sip_trace([address]) +4.1. sip_trace([address]) Store or forward the current processed SIP message in database. It is stored in the form prior applying changes made to it. @@ -438,7 +458,7 @@ modparam("siptrace", "force_send_sock", "sip:10.1.1.2:5000") ONREPLY_ROUTE, BRANCH_ROUTE. Default value is "NULL". - Example 1.18. sip_trace() usage + Example 1.19. sip_trace() usage ... sip_trace(); ... @@ -449,7 +469,7 @@ sip_trace("sip:10.1.1.2:5085"); 5.1. sip_trace -5.1. sip_trace +5.1. sip_trace Name: sip_trace @@ -470,7 +490,7 @@ sip_trace("sip:10.1.1.2:5085"); 6.1. siptrace.status param -6.1. siptrace.status param +6.1. siptrace.status param Name: siptrace.status From 072c88653e280004f86b4c41cfc4d92f3b21af1d Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 12 Jan 2016 14:09:54 +0100 Subject: [PATCH 106/142] core: earlier execution of SREV_NET_DATA_RECV event - allow capturing the traffic before topoh decodes it --- receive.c | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/receive.c b/receive.c index a9e1fc3c075..1c65266e4bd 100644 --- a/receive.c +++ b/receive.c @@ -74,6 +74,39 @@ unsigned int inc_msg_no(void) return ++msg_no; } +/** + * + */ +int sip_check_fline(char* buf, unsigned int len) +{ + char *p; + int m; + + m = 0; + for(p=buf; p=buf) { + if(strncmp(p-8, " SIP/2.0", 8)==0) { + LM_DBG("first line indicates a SIP request\n"); + return 0; + } + } + return -1; + } + } + return -1; +} /** Receive message * WARNING: buf must be 0 terminated (buf[len]=0) or some things might @@ -93,6 +126,16 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) str inb; sr_net_info_t netinfo; + if(sr_event_enabled(SREV_NET_DATA_RECV)) { + if(sip_check_fline(buf, len)==0) { + memset(&netinfo, 0, sizeof(sr_net_info_t)); + netinfo.data.s = buf; + netinfo.data.len = len; + netinfo.rcv = rcv_info; + sr_event_exec(SREV_NET_DATA_RECV, (void*)&netinfo); + } + } + inb.s = buf; inb.len = len; sr_event_exec(SREV_NET_DATA_IN, (void*)&inb); @@ -140,14 +183,6 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) /* ... clear branches from previous message */ clear_branches(); - if(sr_event_enabled(SREV_NET_DATA_RECV)) { - memset(&netinfo, 0, sizeof(sr_net_info_t)); - netinfo.data.s = msg->buf; - netinfo.data.len = msg->len; - netinfo.rcv = rcv_info; - sr_event_exec(SREV_NET_DATA_RECV, (void*)&netinfo); - } - if (msg->first_line.type==SIP_REQUEST){ ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */ if (!IS_SIP(msg)){ From a15affa4d5f35cf2bfdd793b50010318f34f3f08 Mon Sep 17 00:00:00 2001 From: jaybeepee Date: Wed, 13 Jan 2016 11:05:15 +0200 Subject: [PATCH 107/142] modules/ims_usrloc_scscf,modules/ims_registrar_scscf: impus as string from subscription can be created in pkg or shm depending on argument passed --- modules/ims_registrar_scscf/registrar_notify.c | 4 ++-- modules/ims_usrloc_scscf/udomain.c | 13 ++++++++++--- modules/ims_usrloc_scscf/udomain.h | 2 +- modules/ims_usrloc_scscf/usrloc.h | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/modules/ims_registrar_scscf/registrar_notify.c b/modules/ims_registrar_scscf/registrar_notify.c index 77abf905383..8ff38ea31d5 100644 --- a/modules/ims_registrar_scscf/registrar_notify.c +++ b/modules/ims_registrar_scscf/registrar_notify.c @@ -471,7 +471,7 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presen //get IMPU set from the presentity's subscription res = ul.get_impus_from_subscription_as_string(_d, r, - 0/*all unbarred impus*/, &impu_list, &num_impus); + 0/*all unbarred impus*/, &impu_list, &num_impus, 0/*pkg*/); if (res != 0) { LM_WARN("failed to get IMPUs from subscription\n"); ul.unlock_udomain(_d, presentity_uri); @@ -512,7 +512,7 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presen //this is a ulcallback so r_passed domain is already locked res = ul.get_impus_from_subscription_as_string(_d, r_passed, - 0/*all unbarred impus*/, &impu_list, &num_impus); + 0/*all unbarred impus*/, &impu_list, &num_impus, 0/*pkg*/); if (res != 0) { LM_WARN("failed to get IMPUs from subscription\n"); if (impu_list) { diff --git a/modules/ims_usrloc_scscf/udomain.c b/modules/ims_usrloc_scscf/udomain.c index 8fa89f7436d..ed36c53582a 100644 --- a/modules/ims_usrloc_scscf/udomain.c +++ b/modules/ims_usrloc_scscf/udomain.c @@ -626,7 +626,7 @@ int delete_impurecord(udomain_t* _d, str* _aor, struct impurecord* _r) { * barring-(-1) get all records * NB. Remember to free the block of memory pointed to by impus (pkg_malloc) */ -int get_impus_from_subscription_as_string(udomain_t* _d, impurecord_t* impu_rec, int barring, str** impus, int* num_impus) { +int get_impus_from_subscription_as_string(udomain_t* _d, impurecord_t* impu_rec, int barring, str** impus, int* num_impus, int is_shm) { int i, j, count; *num_impus = 0; *impus = 0; @@ -669,9 +669,16 @@ int get_impus_from_subscription_as_string(udomain_t* _d, impurecord_t* impu_rec, LM_DBG("num of records returned is %d and we need %d bytes\n", *num_impus, bytes_needed); len = (sizeof (str)*(*num_impus)) + bytes_needed; - *impus = (str*) pkg_malloc(len); //TODO: rather put this on the stack... dont' fragment pkg.... + if (is_shm) + *impus = (str*) shm_malloc(len); + else + *impus = (str*) pkg_malloc(len); //TODO: rather put this on the stack... dont' fragment pkg.... + if (*impus == 0) { - LM_ERR("no more pkg_mem\n"); + if (is_shm) + LM_ERR("no more shm_mem\n"); + else + LM_ERR("no more pkg_mem\n"); return 1; } char* ptr = (char*) (*impus + *num_impus); diff --git a/modules/ims_usrloc_scscf/udomain.h b/modules/ims_usrloc_scscf/udomain.h index 3bf9d6f549e..d47ff0a2bb9 100644 --- a/modules/ims_usrloc_scscf/udomain.h +++ b/modules/ims_usrloc_scscf/udomain.h @@ -226,7 +226,7 @@ int delete_impurecord(udomain_t* _d, str* _aor, struct impurecord* _r); * barring-0 get all unbarred * barring-(-1) get all records */ -int get_impus_from_subscription_as_string(udomain_t* _d, impurecord_t* impu_rec, int barring, str** impus, int* num_impus); +int get_impus_from_subscription_as_string(udomain_t* _d, impurecord_t* impu_rec, int barring, str** impus, int* num_impus, int is_shm); int get_subscription(str* impi_s, ims_subscription** s, int leave_slot_locked); void add_subscription(ims_subscription* s); diff --git a/modules/ims_usrloc_scscf/usrloc.h b/modules/ims_usrloc_scscf/usrloc.h index a9dfef47a2d..2b5bf874388 100644 --- a/modules/ims_usrloc_scscf/usrloc.h +++ b/modules/ims_usrloc_scscf/usrloc.h @@ -496,7 +496,7 @@ typedef int (*get_subscriber_t)(impurecord_t* urec, str *watcher_contact, str *p typedef int (*add_subscriber_t)(impurecord_t* urec, subscriber_data_t* subscriber_data, reg_subscriber** _reg_subscriber, int db_load); -typedef int (*get_impus_from_subscription_as_string_t)(udomain_t* _d, impurecord_t* impu_rec, int barring, str** impus, int* num_impus); +typedef int (*get_impus_from_subscription_as_string_t)(udomain_t* _d, impurecord_t* impu_rec, int barring, str** impus, int* num_impus, int is_shm); typedef str (*get_presentity_from_subscriber_dialog_t)(str *callid, str *to_tag, str *from_tag); From dce9cea1744c458afae1088935f4c2549689c454 Mon Sep 17 00:00:00 2001 From: jaybeepee Date: Wed, 13 Jan 2016 11:12:37 +0200 Subject: [PATCH 108/142] modules/ims_registrar_scscf: prevent possible deadlock when generating reginfo NOTIFY requests - moved the actual processing of the implicit impu set to create the XML to a separate processing - seperate process will therefore pick up events, build the XML and send the NOTIFY/s - TODO: make framework capable of multiple workers to process events --- .../ims_registrar_scscf/registrar_notify.c | 114 ++++++++---------- .../ims_registrar_scscf/registrar_notify.h | 10 +- 2 files changed, 54 insertions(+), 70 deletions(-) diff --git a/modules/ims_registrar_scscf/registrar_notify.c b/modules/ims_registrar_scscf/registrar_notify.c index 8ff38ea31d5..df1f0b1cd17 100644 --- a/modules/ims_registrar_scscf/registrar_notify.c +++ b/modules/ims_registrar_scscf/registrar_notify.c @@ -57,6 +57,7 @@ #include #include "../../lib/ims/useful_defs.h" +#include "../ims_usrloc_scscf/udomain.h" #define STATE_ACTIVE 1 #define STATE_TERMINATED 0 @@ -437,8 +438,6 @@ int can_subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) { * return 0 on success. anything else failure */ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presentity_uri, str *watcher_contact) { - - str content = {0, 0}; impurecord_t* r; int num_impus; str* impu_list; @@ -481,19 +480,9 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presen return 1; } ul.unlock_udomain((udomain_t*) _d, presentity_uri); - - content = generate_reginfo_full(_d, impu_list, - num_impus, 0, 0); - - if (impu_list) { - pkg_free(impu_list); - } - LM_DBG("About to ceate notification"); - create_notifications(_d, r_passed, presentity_uri, watcher_contact, content, event_type); - if (content.s) pkg_free(content.s); - // if (send_now) notification_timer(0, 0); + create_notifications(_d, r_passed, presentity_uri, watcher_contact, &impu_list, num_impus, event_type); return 0; break; @@ -507,9 +496,6 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presen LM_ERR("this is a contact change passed from ul callback: r_passed and c_passed should both be valid and presentity_uri, watcher_contact and _d should be 0 for ul callback"); return 0; } - - //content = get_reginfo_partial(r_passed, c_passed, event_type); - //this is a ulcallback so r_passed domain is already locked res = ul.get_impus_from_subscription_as_string(_d, r_passed, 0/*all unbarred impus*/, &impu_list, &num_impus, 0/*pkg*/); @@ -526,19 +512,9 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presen LM_ERR("Unable to register usrloc domain....aborting\n"); return 0; } - // - content = generate_reginfo_full(udomain, impu_list, - num_impus, &r_passed->public_identity, 1); - // - if (impu_list) { - pkg_free(impu_list); - } - LM_DBG("About to ceate notification"); - create_notifications(_d, r_passed, presentity_uri, watcher_contact, content, event_type); - if (content.s) pkg_free(content.s); - // if (send_now) notification_timer(0, 0); + create_notifications(_d, r_passed, presentity_uri, watcher_contact, &impu_list, num_impus, event_type); return 1; default: @@ -1391,7 +1367,7 @@ static str subs_active = {"active;expires=", 15}; * @param content - the body content * @param expires - the remaining subcription expiration time in seconds */ -void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity_uri, str *watcher_contact, str content, int event_type) { +void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity_uri, str *watcher_contact, str** impus, int num_impus, int event_type) { reg_notification *n; reg_subscriber *s; @@ -1432,7 +1408,7 @@ void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity if (s->expires > act_time) { LM_DBG("Expires is greater than current time!"); - subscription_state.s = pkg_malloc(32); + subscription_state.s = (char*) pkg_malloc(32 * sizeof (char*)); subscription_state.len = 0; if (subscription_state.s) { @@ -1462,8 +1438,9 @@ void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity version = s->version + 1; ul.update_subscriber(r, &s, 0, &local_cseq, &version); - n = new_notification(subscription_state, content_type, content, s); + n = new_notification(subscription_state, content_type, impus, num_impus, s); if (n) { + n->_d = _t; LM_DBG("Notification exists - about to add it"); add_notification(n); } else { @@ -1488,15 +1465,16 @@ void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity version = s->version + 1; ul.update_subscriber(r, &s, 0, &local_cseq, &version); - n = new_notification(subscription_state, content_type, content, s); - if (n) { - LM_DBG("Notification exists - about to add it"); - add_notification(n); + n = new_notification(subscription_state, content_type, impus, num_impus, s); + if (n) { + n->_d = _t; + LM_DBG("Notification exists - about to add it"); + add_notification(n); - } else { - LM_DBG("Notification does not exist"); - } -// } + } else { + LM_DBG("Notification does not exist"); + } + // } } s = s->next; @@ -1655,7 +1633,7 @@ static void process_xml_for_contact(str* buf, str* pad, ucontact_t* ptr) { * @returns the str with the XML content * if its a new subscription we do things like subscribe to updates on IMPU, etc */ -str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *primary_impu, int primary_locked) { +str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus) { str x = {0, 0}; str buf, pad; char bufc[MAX_REGINFO_SIZE], padc[MAX_REGINFO_SIZE]; @@ -1927,12 +1905,23 @@ static int free_tm_dlg(dlg_t * td) { void send_notification(reg_notification * n) { str h = {0, 0}; - + str content = {0, 0}; uac_req_t uac_r; dlg_t* td = NULL; + struct udomain* domain = (struct udomain*) n->_d; + if (!domain) { + ul.register_udomain("location", &domain); + } + + LM_DBG("Have a notification to send for the following IMPUs using domain [%.*s]\n", domain->name->len, domain->name->s); + + + content = generate_reginfo_full(domain, n->impus, n->num_impus); + str method = {"NOTIFY", 6}; + LM_DBG("Notification content: [%.*s]", content.len, content.s); LM_DBG("DBG:send_notification: NOTIFY about <%.*s>\n", n->watcher_uri.len, n->watcher_uri.s); h.len = 0; @@ -1975,14 +1964,12 @@ void send_notification(reg_notification * n) { return; } - - if (n->content.len) { - + if (content.len) { LM_DBG("Notification content exists - about to send notification with subscription state: [%.*s] content_type: [%.*s] content: [%.*s] : presentity_uri: [%.*s] watcher_uri: [%.*s]", - n->subscription_state.len, n->subscription_state.s, n->content_type.len, n->content_type.s, n->content.len, n->content.s, + n->subscription_state.len, n->subscription_state.s, n->content_type.len, n->content_type.s, content.len, content.s, n->presentity_uri.len, n->presentity_uri.s, n->watcher_uri.len, n->watcher_uri.s); - set_uac_req(&uac_r, &method, &h, &n->content, td, TMCB_LOCAL_COMPLETED, + set_uac_req(&uac_r, &method, &h, &content, td, TMCB_LOCAL_COMPLETED, uac_request_cb, 0); tmb.t_request_within(&uac_r); } else { @@ -2012,26 +1999,17 @@ void send_notification(reg_notification * n) { * @returns the r_notification or NULL on error */ reg_notification * new_notification(str subscription_state, - str content_type, str content, reg_subscriber * r) { - + str content_type, str** impus, int num_impus, reg_subscriber * r) { + int i; reg_notification *n = 0; - - str buf; - char bufc[MAX_REGINFO_SIZE]; - - if (content.len > MAX_REGINFO_SIZE) { - LM_ERR("content size (%d) exceeds MAX_REGINFO_SIZE (%d)!\n", content.len, MAX_REGINFO_SIZE); - return 0; - } - - buf.s = bufc; - buf.len = snprintf(buf.s, MAX_REGINFO_SIZE, content.s, r->version); - int len; char *p; len = sizeof (reg_notification) + r->call_id.len + r->from_tag.len + r->to_tag.len + r->watcher_uri.len + r->watcher_contact.len + - r->record_route.len + r->sockinfo_str.len + r->presentity_uri.len + subscription_state.len + content_type.len + buf.len; + r->record_route.len + r->sockinfo_str.len + r->presentity_uri.len + subscription_state.len + content_type.len + (num_impus*sizeof(str)); // + buf.len; + for (i=0; ilen; + } LM_DBG("Creating new notification"); @@ -2106,12 +2084,16 @@ reg_notification * new_notification(str subscription_state, p += content_type.len; LM_DBG("Notification content type: [%.*s]", n->content_type.len, n->content_type.s); - n->content.s = p; - n->content.len = buf.len; - memcpy(p, buf.s, buf.len); - p += buf.len; - LM_DBG("Notification content: [%.*s]", n->content.len, n->content.s); - + n->impus = p; + p += sizeof(str)*num_impus; + for (i=0; iimpus[i].s = p; + memcpy(p, impus[i]->s, impus[i]->len); + n->impus[i].len = impus[i]->len; + p += impus[i]->len; + } + n->num_impus = num_impus; + if (p != (((char*) n) + len)) { LM_CRIT("buffer overflow\n"); free_notification(n); diff --git a/modules/ims_registrar_scscf/registrar_notify.h b/modules/ims_registrar_scscf/registrar_notify.h index ccb9f6c0721..f3d5ac1782b 100644 --- a/modules/ims_registrar_scscf/registrar_notify.h +++ b/modules/ims_registrar_scscf/registrar_notify.h @@ -62,12 +62,14 @@ typedef struct _reg_notification { str subscription_state; /**< Subscription-state header value*/ str content_type; /**< content type */ - str content; /**< content */ str watcher_contact; str watcher_uri; str presentity_uri; + struct udomain* _d; + str* impus; + int num_impus; unsigned int local_cseq; str call_id; @@ -126,11 +128,11 @@ int subscribe_reply(struct sip_msg *msg, int code, char *text, int *expires, str int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presentity_uri, str *watcher_contact); -str generate_reginfo_full(udomain_t* _t, str* impu_list, int new_subscription, str *primary_impu, int primary_locked); +str generate_reginfo_full(udomain_t* _t, str* impu_list, int new_subscription); str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type); -void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity_uri, str *watcher_contact, str content, int event_type); +void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity_uri, str *watcher_contact, str** impus, int num_impus, int event_type); void notification_event_process(); @@ -141,7 +143,7 @@ void send_notification(reg_notification * n); void add_notification(reg_notification *n); reg_notification* new_notification(str subscription_state, - str content_type, str content, reg_subscriber* r); + str content_type, str** impus, int num_impus, reg_subscriber* r); dlg_t* build_dlg_t_from_notification(reg_notification* n); From caeda232d6e2d29a5da202c9db244b407c94ede2 Mon Sep 17 00:00:00 2001 From: Ian Yu-Hsun Lin Date: Thu, 14 Jan 2016 16:02:25 +0800 Subject: [PATCH 109/142] registrar: reg_xavp_cfg should not be reset when sock_flag is not set - since there are functions like `registered()` would use it - reported by Jayesh Nambiar (@jayesh1017) in the comment of GH#470 --- modules/registrar/reg_mod.c | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/registrar/reg_mod.c b/modules/registrar/reg_mod.c index 0d7c5acf0f7..f859db4df6c 100644 --- a/modules/registrar/reg_mod.c +++ b/modules/registrar/reg_mod.c @@ -365,7 +365,6 @@ static int mod_init(void) } else if (reg_xavp_cfg.s) { if (reg_xavp_cfg.len == 0 || sock_flag == -1) { LM_WARN("empty reg_xavp_cfg or sock_flag no set -> resetting\n"); - reg_xavp_cfg.len = 0; sock_flag = -1; } } else if (sock_flag!=-1) { From 6f46f87acf7b3772a2bc8902e6e73e0bdc293851 Mon Sep 17 00:00:00 2001 From: jaybeepee Date: Thu, 14 Jan 2016 11:22:07 +0200 Subject: [PATCH 110/142] modules/ims_charging: add adjustments for rounding errors that creep in during interim charges - this is a result of Ro interface only supporting second-based resolution in diam. msgs. to OCS --- modules/ims_charging/ims_ro.c | 22 +++++++++++++++++++++- modules/ims_charging/ro_timer.c | 8 ++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/modules/ims_charging/ims_ro.c b/modules/ims_charging/ims_ro.c index 88647887943..3dafc2bc9b5 100644 --- a/modules/ims_charging/ims_ro.c +++ b/modules/ims_charging/ims_ro.c @@ -755,9 +755,29 @@ void send_ccr_stop(struct ro_session *ro_session) { long used = 0; str user_name = {0, 0}; int ret = 0; + time_t stop_time; + time_t actual_time_micros; + int actual_time_seconds; + + stop_time = get_current_time_micro(); + + if (ro_session->start_time == 0) + actual_time_micros = 0; + else + actual_time_micros = stop_time - ro_session->start_time; + + actual_time_seconds = (actual_time_micros + (1000000 - 1)) / (float) 1000000; if (ro_session->event_type != pending) { - used = rint((get_current_time_micro() - ro_session->last_event_timestamp)/(float)1000000); + used = rint((stop_time - ro_session->last_event_timestamp) / (float) 1000000); + LM_DBG("Final used number of seconds for session is %ld\n", used); + } + + LM_DBG("Call started at %ld and ended at %ld and lasted %d seconds and so far we have billed for %ld seconds\n", ro_session->start_time, stop_time, + actual_time_seconds, ro_session->billed + used); + if (ro_session->billed + used < actual_time_seconds) { + LM_DBG("Making adjustment by adding %ld seconds\n", actual_time_seconds - (ro_session->billed + used)); + used += actual_time_seconds - (ro_session->billed + used); } counter_add(ims_charging_cnts_h.billed_secs, (int)used); diff --git a/modules/ims_charging/ro_timer.c b/modules/ims_charging/ro_timer.c index 40f3c4240fb..efcc5ccf2fc 100644 --- a/modules/ims_charging/ro_timer.c +++ b/modules/ims_charging/ro_timer.c @@ -380,6 +380,7 @@ void resume_ro_session_ontimeout(struct interim_ccr *i_req) { void ro_session_ontimeout(struct ro_tl *tl) { time_t now, call_time; long used_secs; + int adjustment; LM_DBG("We have a fired timer [p=%p] and tl=[%i].\n", tl, tl->timeout); @@ -419,6 +420,12 @@ void ro_session_ontimeout(struct ro_tl *tl) { used_secs = rint((now - ro_session->last_event_timestamp) / (float) 1000000); call_time = rint((now - ro_session->start_time) / (float) 1000000); + if ((used_secs + ro_session->billed) < (call_time)) { + adjustment = call_time - (used_secs + ro_session->billed); + LM_DBG("Making adjustment for Ro interim timer by adding %d seconds\n", adjustment); + used_secs += adjustment; + } + counter_add(ims_charging_cnts_h.billed_secs, used_secs); if (ro_session->callid.s != NULL @@ -444,6 +451,7 @@ void ro_session_ontimeout(struct ro_tl *tl) { // Apply for more credit. // // The function call will return immediately and we will receive the reply asynchronously via a callback + ro_session->billed += used_secs; send_ccr_interim(ro_session, (unsigned int) used_secs, interim_request_credits); return; } else { From 4de2390a4071530e808eddd86ee8926ec51524eb Mon Sep 17 00:00:00 2001 From: Mikko Lehto Date: Fri, 15 Jan 2016 01:28:12 +0200 Subject: [PATCH 111/142] modules/ndb_mongodb: fixes documentation typo --- modules/ndb_mongodb/README | 2 +- modules/ndb_mongodb/doc/ndb_mongodb_admin.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ndb_mongodb/README b/modules/ndb_mongodb/README index 0c655e52a9e..01b1ce5de3f 100644 --- a/modules/ndb_mongodb/README +++ b/modules/ndb_mongodb/README @@ -105,7 +105,7 @@ Chapter 1. Admin Guide 3.1. server (str) - Specify the details to connect to REDIS server. It takes a list of + Specify the details to connect to MongoDB server. It takes a list of attribute=value separated by semicolon, the attributes can be name and uri. Name is a generic identifier to be used with module functions. The uri parameter must be a valid MongoDB database connection string. diff --git a/modules/ndb_mongodb/doc/ndb_mongodb_admin.xml b/modules/ndb_mongodb/doc/ndb_mongodb_admin.xml index 5df46601c20..ec43474642f 100644 --- a/modules/ndb_mongodb/doc/ndb_mongodb_admin.xml +++ b/modules/ndb_mongodb/doc/ndb_mongodb_admin.xml @@ -62,7 +62,7 @@
<varname>server</varname> (str) - Specify the details to connect to REDIS server. It takes a list of + Specify the details to connect to MongoDB server. It takes a list of attribute=value separated by semicolon, the attributes can be name and uri. Name is a generic identifier to be used with module functions. The uri parameter must be a valid From 5d2d7237ac0d64689b3ff4d6be256ff4bd74cef7 Mon Sep 17 00:00:00 2001 From: Mikko Lehto Date: Fri, 15 Jan 2016 02:48:11 +0200 Subject: [PATCH 112/142] modules/statsd: use C99 boolean --- modules/statsd/lib_statsd.c | 38 ++++++++++++++++++------------------- modules/statsd/lib_statsd.h | 20 +++++++++---------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/modules/statsd/lib_statsd.c b/modules/statsd/lib_statsd.c index 52820e51b76..6492ef219b9 100644 --- a/modules/statsd/lib_statsd.c +++ b/modules/statsd/lib_statsd.c @@ -24,13 +24,13 @@ static StatsConnection statsd_connection = { "8125" }; -int statsd_connect(void){ +bool statsd_connect(void){ struct addrinfo *serverAddr; int rc, error; if (statsd_socket.sock > 0){ - return True; + return true; } error = getaddrinfo( @@ -41,62 +41,62 @@ int statsd_connect(void){ LM_ERR( "Statsd: could not initiate server information (%s)\n", gai_strerror(error)); - return False; + return false; } statsd_socket.sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (statsd_socket.sock == 0 ){ LM_ERR("Statsd: could not initiate a connect to statsd\n"); - return False; + return false; } rc = connect( statsd_socket.sock, serverAddr->ai_addr, serverAddr->ai_addrlen); if (rc < 0){ LM_ERR("Statsd: could not initiate a connect to statsd\n"); - return False; + return false; } - return True; + return true; } -int send_command(char *command){ +bool send_command(char *command){ int send_result; if (!statsd_connect()){ - return False; + return false; } send_result = send(statsd_socket.sock, command, strlen(command), 0); if ( send_result < 0){ LM_ERR("could not send the correct info to statsd (%i| %s)\n", send_result, strerror(errno)); - return True; + return true; } LM_DBG("Sent to statsd (%s)", command); - return True; + return true; } -int statsd_set(char *key, char *value){ +bool statsd_set(char *key, char *value){ char* end = 0; char command[254]; int val; val = strtol(value, &end, 0); if (*end){ LM_ERR("statsd_count could not use the provide value(%s)\n", value); - return False; + return false; } snprintf(command, sizeof command, "%s:%i|s\n", key, val); return send_command(command); } -int statsd_gauge(char *key, char *value){ +bool statsd_gauge(char *key, char *value){ char command[254]; snprintf(command, sizeof command, "%s:%s|g\n", key, value); return send_command(command); } -int statsd_count(char *key, char *value){ +bool statsd_count(char *key, char *value){ char* end = 0; char command[254]; int val; @@ -104,19 +104,19 @@ int statsd_count(char *key, char *value){ val = strtol(value, &end, 0); if (*end){ LM_ERR("statsd_count could not use the provide value(%s)\n", value); - return False; + return false; } snprintf(command, sizeof command, "%s:%i|c\n", key, val); return send_command(command); } -int statsd_timing(char *key, int value){ +bool statsd_timing(char *key, int value){ char command[254]; snprintf(command, sizeof command, "%s:%i|ms\n", key, value); return send_command(command); } -int statsd_init(char *ip, char *port){ +bool statsd_init(char *ip, char *port){ if (ip != NULL){ statsd_connection.ip = ip; @@ -127,7 +127,7 @@ int statsd_init(char *ip, char *port){ return statsd_connect(); } -int statsd_destroy(void){ +bool statsd_destroy(void){ statsd_socket.sock = 0; - return True; + return true; } diff --git a/modules/statsd/lib_statsd.h b/modules/statsd/lib_statsd.h index b7d178e9c25..d3064c21ea2 100644 --- a/modules/statsd/lib_statsd.h +++ b/modules/statsd/lib_statsd.h @@ -1,8 +1,6 @@ +#include #define BUFFER_SIZE 8192 -typedef int Bool; -#define True 1 -#define False 0 typedef struct StatsConnection{ char *ip; @@ -17,11 +15,11 @@ typedef struct StatsdSocket { char data[BUFFER_SIZE]; // buffer for the answer data } StatsdSocket; -int statsd_connect(void); -int send_command(char *command); -int statsd_set(char *key, char *value); -int statsd_gauge(char *key, char *value); -int statsd_count(char *key, char *value); -int statsd_timing(char *key, int value); -int statsd_init(char *ip, char *port); -int statsd_destroy(void); +bool statsd_connect(void); +bool send_command(char *command); +bool statsd_set(char *key, char *value); +bool statsd_gauge(char *key, char *value); +bool statsd_count(char *key, char *value); +bool statsd_timing(char *key, int value); +bool statsd_init(char *ip, char *port); +bool statsd_destroy(void); From 648d95e126a13986684db94136dc47d69a7cc27c Mon Sep 17 00:00:00 2001 From: Mikko Lehto Date: Fri, 15 Jan 2016 02:48:39 +0200 Subject: [PATCH 113/142] modules/nat_traversal: use C99 boolean --- modules/nat_traversal/nat_traversal.c | 72 +++++++++++++-------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/modules/nat_traversal/nat_traversal.c b/modules/nat_traversal/nat_traversal.c index 67b65fad04c..0acdd1725d1 100644 --- a/modules/nat_traversal/nat_traversal.c +++ b/modules/nat_traversal/nat_traversal.c @@ -34,6 +34,7 @@ traversal for SIP signaling. */ +#include #include #include #include @@ -98,12 +99,7 @@ MODULE_VERSION #define STR_HAS_IPREFIX(str, prefix) ((str).len>(prefix).len && strncasecmp((prefix).s, (str).s, (prefix).len)==0) -typedef int Bool; -#define True 1 -#define False 0 - - -typedef Bool (*NatTestFunction)(struct sip_msg *msg); +typedef bool (*NatTestFunction)(struct sip_msg *msg); typedef enum { NTNone=0, @@ -162,7 +158,7 @@ typedef struct Dialog_Param { char *caller_uri; char *callee_uri; time_t expire; - Bool confirmed; + bool confirmed; gen_lock_t lock; struct { char **uri; @@ -194,9 +190,9 @@ static int NAT_Keepalive(struct sip_msg *msg); static int FixContact(struct sip_msg *msg); static int ClientNatTest(struct sip_msg *msg, unsigned int tests); -static Bool test_private_contact(struct sip_msg *msg); -static Bool test_source_address(struct sip_msg *msg); -static Bool test_private_via(struct sip_msg *msg); +static bool test_private_contact(struct sip_msg *msg); +static bool test_source_address(struct sip_msg *msg); +static bool test_private_via(struct sip_msg *msg); static INLINE char* shm_strdup(char *source); @@ -215,7 +211,7 @@ static int pv_get_source_uri(struct sip_msg *msg, pv_param_t *param, pv_value_t // static HashTable *nat_table = NULL; -static Bool keepalive_disabled = False; +static bool keepalive_disabled = false; static unsigned int keepalive_interval = 60; @@ -225,7 +221,7 @@ static Keepalive_Params keepalive_params = {"NOTIFY", NULL, "", "", 0, 0, ""}; struct tm_binds tm_api; struct dlg_binds dlg_api; -Bool have_dlg_api = False; +bool have_dlg_api = false; static int dialog_flag = -1; static unsigned dialog_default_timeout = 12*3600; // 12 hours @@ -466,7 +462,7 @@ NAT_Contact_del(NAT_Contact *contact) } -static Bool +static bool NAT_Contact_match(NAT_Contact *contact, const char *uri) { return strcmp(contact->uri, uri)==0; @@ -674,24 +670,24 @@ Dialog_Param_del(Dialog_Param *param) // This function assumes the caller has locked the Dialog_Param while operating on it // -static Bool +static bool Dialog_Param_has_candidate(Dialog_Param *param, char *candidate) { int i; for (i=0; icallee_candidates.count; i++) { if (strcmp(candidate, param->callee_candidates.uri[i])==0) { - return True; + return true; } } - return False; + return false; } // This function assumes the caller has locked the Dialog_Param while operating on it // -static Bool +static bool Dialog_Param_add_candidate(Dialog_Param *param, char *candidate) { char **new_uri, *new_candidate; @@ -703,7 +699,7 @@ Dialog_Param_add_candidate(Dialog_Param *param, char *candidate) new_uri = shm_realloc(param->callee_candidates.uri, new_size * sizeof(char*)); if (!new_uri) { LM_ERR("failed to grow callee_candidates uri list\n"); - return False; + return false; } param->callee_candidates.uri = new_uri; param->callee_candidates.size = new_size; @@ -712,13 +708,13 @@ Dialog_Param_add_candidate(Dialog_Param *param, char *candidate) new_candidate = shm_strdup(candidate); if (!new_candidate) { LM_ERR("cannot allocate shared memory for new candidate uri\n"); - return False; + return false; } param->callee_candidates.uri[param->callee_candidates.count] = new_candidate; param->callee_candidates.count++; - return True; + return true; } @@ -774,30 +770,30 @@ shm_strdup(char *source) } -static Bool +static bool get_contact_uri(struct sip_msg* msg, struct sip_uri *uri, contact_t **_c) { if ((parse_headers(msg, HDR_CONTACT_F, 0) == -1) || !msg->contact) - return False; + return false; if (!msg->contact->parsed && parse_contact(msg->contact) < 0) { LM_ERR("cannot parse the Contact header\n"); - return False; + return false; } *_c = ((contact_body_t*)msg->contact->parsed)->contacts; if (*_c == NULL) { - return False; + return false; } if (parse_uri((*_c)->uri.s, (*_c)->uri.len, uri) < 0 || uri->host.len <= 0) { LM_ERR("cannot parse the Contact URI\n"); - return False; + return false; } - return True; + return true; } @@ -828,10 +824,10 @@ rfc1918address(str *address) // Test if address of signaling is different from address in 1st Via field -static Bool +static bool test_source_address(struct sip_msg *msg) { - Bool different_ip, different_port; + bool different_ip, different_port; int via1_port; different_ip = received_via_test(msg); @@ -843,21 +839,21 @@ test_source_address(struct sip_msg *msg) // Test if Contact field contains a private IP address as defined in RFC1918 -static Bool +static bool test_private_contact(struct sip_msg *msg) { struct sip_uri uri; contact_t* contact; if (!get_contact_uri(msg, &uri, &contact)) - return False; + return false; return is_private_address(&(uri.host)); } // Test if top Via field contains a private IP address as defined in RFC1918 -static Bool +static bool test_private_via(struct sip_msg *msg) { return is_private_address(&(msg->via1->host)); @@ -898,7 +894,7 @@ get_register_expire(struct sip_msg *request, struct sip_msg *reply) param_t *expires_param; time_t now, expire=0; unsigned exp; - Bool matched; + bool matched; if (!request->contact) return 0; @@ -935,7 +931,7 @@ get_register_expire(struct sip_msg *request, struct sip_msg *reply) } for (contact=contact_body->contacts; contact; contact=contact->next) { - for (r_hdr=reply->contact, matched=False; r_hdr && !matched; r_hdr=next_sibling_hdr(r_hdr)) { + for (r_hdr=reply->contact, matched=false; r_hdr && !matched; r_hdr=next_sibling_hdr(r_hdr)) { if (!r_hdr->parsed && parse_contact(r_hdr) < 0) { LM_ERR("failed to parse the Contact header body in reply\n"); continue; @@ -946,7 +942,7 @@ get_register_expire(struct sip_msg *request, struct sip_msg *reply) expires_param = r_contact->expires; if (expires_param && expires_param->body.len && str2int(&expires_param->body, &exp) == 0) expire = max(expire, exp); - matched = True; + matched = true; break; } } @@ -1092,7 +1088,7 @@ __dialog_confirmed(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params lock_get(¶m->lock); - param->confirmed = True; + param->confirmed = true; callee_uri = get_source_uri(_params->rpl); @@ -1684,7 +1680,7 @@ restore_keepalive_state(void) res = fscanf(f, STATE_FILE_HEADER); // skip header - while (True) { + while (true) { res = fscanf(f, "%63s %63s %ld %ld", uri, socket, &rtime, &stime); if (res == EOF) { if (ferror(f)) @@ -1734,7 +1730,7 @@ mod_init(void) if (keepalive_interval <= 0) { LM_NOTICE("keepalive functionality is disabled from the configuration\n"); - keepalive_disabled = True; + keepalive_disabled = true; return 0; } @@ -1764,7 +1760,7 @@ mod_init(void) param = find_param_export(find_module_by_name("dialog"), "dlg_flag", INT_PARAM, &type); if (param) { - have_dlg_api = True; + have_dlg_api = true; dialog_flag = *param; From 2370c6dccec38be8576bd4234ecbbc5883972058 Mon Sep 17 00:00:00 2001 From: Carsten Bock Date: Fri, 15 Jan 2016 11:04:15 +0100 Subject: [PATCH 114/142] ims_charging: Added missing field in Ro-Session (introduced in previous commit) --- modules/ims_charging/ro_session_hash.h | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ims_charging/ro_session_hash.h b/modules/ims_charging/ro_session_hash.h index fa92ed96e3a..8fa622f3f7e 100644 --- a/modules/ims_charging/ro_session_hash.h +++ b/modules/ims_charging/ro_session_hash.h @@ -72,6 +72,7 @@ struct ro_session { int rating_group; int service_identifier; unsigned int is_final_allocation; + unsigned int billed; }; /*! entries in the main ro_session table */ From 8e8a71cc0b589bb881f56bbef370a1d19863d038 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Fri, 15 Jan 2016 12:04:54 +0200 Subject: [PATCH 115/142] debugger: Fix dbg_sip_msg() segfault Fix dbg_sip_msg() segfault when the function is called with no parameters. Change the dbg_sip_msg() output format. --- modules/debugger/debugger_mod.c | 61 ++++++++++++++++----------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/modules/debugger/debugger_mod.c b/modules/debugger/debugger_mod.c index e37ab83a5f0..8334b97a9c9 100644 --- a/modules/debugger/debugger_mod.c +++ b/modules/debugger/debugger_mod.c @@ -707,6 +707,8 @@ static int fixup_dbg_sip_msg(void** param, int param_no) int level; struct action *dbg_sip_msg_action; + LM_DBG("dbg_sip_msg() called with %d params\n", param_no); + switch(param_no) { case 2: @@ -716,8 +718,9 @@ static int fixup_dbg_sip_msg(void** param, int param_no) return E_UNSPEC; } - *param = (void*)(long)facility; + *param = (void*)(long)facility; break; + case 1: switch(((char*)(*param))[2]) { @@ -737,6 +740,15 @@ static int fixup_dbg_sip_msg(void** param, int param_no) *param = (void*)(long)level; break; + + case 0: + _dbg_sip_msg_cline = -1; + return 0; + + default: + // should not reach here + _dbg_sip_msg_cline = -1; + return -1; } /* save the config line where this config function was called */ @@ -815,36 +827,23 @@ static int w_dbg_sip_msg(struct sip_msg* msg, char *level, char *facility) new_buf_offs = 0; process_lumps(msg, msg->body_lumps, bdy_lumps, &new_buf_offs, &orig_offs, &send_info, flag); - /* do the print */ - if (hdr_lumps != NULL && bdy_lumps != NULL) { - LOG_FC(ifacility, ilevel, "CONFIG LINE %d\n%s%.*s%s%s%s%s%s", - _dbg_sip_msg_cline, - start_txt, - obuf.len, obuf.s, - hdr_txt, hdr_lumps, - bdy_txt, bdy_lumps, - end_txt); - } else if (hdr_lumps != NULL) { - LOG_FC(ifacility, ilevel, "CONFIG LINE %d\n%s%.*s%s%s%s", - _dbg_sip_msg_cline, - start_txt, - obuf.len, obuf.s, - hdr_txt, hdr_lumps, - end_txt); - } else if (bdy_lumps != NULL) { - LOG_FC(ifacility, ilevel, "CONFIG LINE %d\n%s%.*s%s%s%s", - _dbg_sip_msg_cline, - start_txt, - obuf.len, obuf.s, - bdy_txt, bdy_lumps, - end_txt); - } else { - LOG_FC(ifacility, ilevel, "CONFIG LINE %d\n%s%.*s%s", - _dbg_sip_msg_cline, - start_txt, - obuf.len, obuf.s, - end_txt); - } + /* do the print */ + if (_dbg_sip_msg_cline < 0 ) { + LOG_FC(ifacility, ilevel, "CONFIG LINE unknown\n%s%.*s%s%s%s%s%s", + start_txt, + obuf.len, obuf.s, + hdr_txt, hdr_lumps, + bdy_txt, bdy_lumps, + end_txt); + } else { + LOG_FC(ifacility, ilevel, "CONFIG LINE %d\n%s%.*s%s%s%s%s%s", + _dbg_sip_msg_cline, + start_txt, + obuf.len, obuf.s, + hdr_txt, hdr_lumps, + bdy_txt, bdy_lumps, + end_txt); + } /* free lumps */ if (hdr_lumps) { From 21a7ce6fe07c2e645519603eaff908dfd96be3cc Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Fri, 15 Jan 2016 12:28:02 +0200 Subject: [PATCH 116/142] debugger: debugger_mod.c indentation Tab-like indentations for debugger_mod.c file. --- modules/debugger/debugger_mod.c | 288 ++++++++++++++++---------------- 1 file changed, 144 insertions(+), 144 deletions(-) diff --git a/modules/debugger/debugger_mod.c b/modules/debugger/debugger_mod.c index 8334b97a9c9..9f8186d5259 100644 --- a/modules/debugger/debugger_mod.c +++ b/modules/debugger/debugger_mod.c @@ -98,12 +98,12 @@ static cmd_export_t cmds[]={ fixup_dbg_pv_dump, 0, ANY_ROUTE}, {"dbg_pv_dump", (cmd_function)w_dbg_dump, 2, fixup_dbg_pv_dump, 0, ANY_ROUTE}, - {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 0, - fixup_dbg_sip_msg, 0, REQUEST_ROUTE}, - {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 1, - fixup_dbg_sip_msg, 0, REQUEST_ROUTE}, - {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 2, - fixup_dbg_sip_msg, 0, REQUEST_ROUTE}, + {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 0, + fixup_dbg_sip_msg, 0, REQUEST_ROUTE}, + {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 1, + fixup_dbg_sip_msg, 0, REQUEST_ROUTE}, + {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 2, + fixup_dbg_sip_msg, 0, REQUEST_ROUTE}, {0, 0, 0, 0, 0, 0} }; @@ -320,8 +320,8 @@ static struct mi_root* mi_get_dbg_mod_level(struct mi_root *cmd_tree, void *para } if ((attr = add_mi_attr(crt_node, MI_DUP_VALUE, - level_attr.s, level_attr.len, - level_str.s, level_str.len)) == 0) { + level_attr.s, level_attr.len, + level_str.s, level_str.len)) == 0) { LM_ERR("cannot add attributes to the node\n"); goto error; } @@ -383,8 +383,8 @@ static struct mi_root* mi_get_dbg_mod_facility(struct mi_root *cmd_tree, void *p } if ((attr = add_mi_attr(crt_node, MI_DUP_VALUE, - facility_attr.s, facility_attr.len, - facility_str.s, facility_str.len)) == 0) { + facility_attr.s, facility_attr.len, + facility_str.s, facility_str.len)) == 0) { LM_ERR("cannot add attributes to the node\n"); goto error; } @@ -439,7 +439,7 @@ static int mod_init(void) /* anyhow, should fail before */ if (!dbg_cfg) { - return -1; + return -1; } LM_DBG("cfg level_mode:%d facility_mode:%d hash_size:%d\n", @@ -556,7 +556,7 @@ static int fixup_dbg_pv_dump(void** param, int param_no) break; } - return 0; + return 0; } /** @@ -604,7 +604,7 @@ static int fixup_dbg_breakpoint(void** param, int param_no) a = dbg_fixup_get_action(param, param_no); p = (char*)(*param); - return dbg_add_breakpoint(a, (*p=='0')?0:1); + return dbg_add_breakpoint(a, (*p=='0')?0:1); } static int dbg_mod_level_param(modparam_t type, void *val) @@ -631,7 +631,7 @@ static int dbg_mod_level_param(modparam_t type, void *val) s.len = p - s.s; if (!dbg_cfg) { - return -1; + return -1; } LM_DBG("cfg level_mode:%d hash_size:%d\n", @@ -679,7 +679,7 @@ static int dbg_mod_facility_param(modparam_t type, void *val) s.len = p - s.s; if (!dbg_cfg) { - return -1; + return -1; } LM_DBG("cfg facility_mode:%d hash_size:%d\n", @@ -703,59 +703,59 @@ static int dbg_mod_facility_param(modparam_t type, void *val) static int fixup_dbg_sip_msg(void** param, int param_no) { - int facility; - int level; - struct action *dbg_sip_msg_action; + int facility; + int level; + struct action *dbg_sip_msg_action; LM_DBG("dbg_sip_msg() called with %d params\n", param_no); - switch(param_no) - { - case 2: - facility = str2facility((char*)*(param)); - if (facility == -1) { - LM_ERR("invalid log facility configured"); - return E_UNSPEC; - } - - *param = (void*)(long)facility; - break; - - case 1: - switch(((char*)(*param))[2]) - { - /* add L_OFFSET because L_WARN is consdered null pointer */ - case 'A': level = L_ALERT + L_OFFSET; break; - case 'B': level = L_BUG + L_OFFSET; break; - case 'C': level = L_CRIT2 + L_OFFSET; break; - case 'E': level = L_ERR + L_OFFSET; break; - case 'W': level = L_WARN + L_OFFSET; break; - case 'N': level = L_NOTICE + L_OFFSET; break; - case 'I': level = L_INFO + L_OFFSET; break; - case 'D': level = L_DBG + L_OFFSET; break; - default: - LM_ERR("unknown log level\n"); - return E_UNSPEC; - } - - *param = (void*)(long)level; - break; - - case 0: - _dbg_sip_msg_cline = -1; - return 0; - - default: - // should not reach here - _dbg_sip_msg_cline = -1; - return -1; - } + switch(param_no) + { + case 2: + facility = str2facility((char*)*(param)); + if (facility == -1) { + LM_ERR("invalid log facility configured"); + return E_UNSPEC; + } + + *param = (void*)(long)facility; + break; + + case 1: + switch(((char*)(*param))[2]) + { + /* add L_OFFSET because L_WARN is consdered null pointer */ + case 'A': level = L_ALERT + L_OFFSET; break; + case 'B': level = L_BUG + L_OFFSET; break; + case 'C': level = L_CRIT2 + L_OFFSET; break; + case 'E': level = L_ERR + L_OFFSET; break; + case 'W': level = L_WARN + L_OFFSET; break; + case 'N': level = L_NOTICE + L_OFFSET; break; + case 'I': level = L_INFO + L_OFFSET; break; + case 'D': level = L_DBG + L_OFFSET; break; + default: + LM_ERR("unknown log level\n"); + return E_UNSPEC; + } + + *param = (void*)(long)level; + break; + + case 0: + _dbg_sip_msg_cline = -1; + return 0; - /* save the config line where this config function was called */ - dbg_sip_msg_action = dbg_fixup_get_action(param, param_no); - _dbg_sip_msg_cline = dbg_sip_msg_action->cline; + default: + // should not reach here + _dbg_sip_msg_cline = -1; + return -1; + } + + /* save the config line where this config function was called */ + dbg_sip_msg_action = dbg_fixup_get_action(param, param_no); + _dbg_sip_msg_cline = dbg_sip_msg_action->cline; - return 0; + return 0; } /** @@ -764,95 +764,95 @@ static int fixup_dbg_sip_msg(void** param, int param_no) */ static int w_dbg_sip_msg(struct sip_msg* msg, char *level, char *facility) { - int ilevel = cfg_get(core, core_cfg, debug); - int ifacility= cfg_get(core, core_cfg, log_facility); - int flag = FLAG_MSG_LUMPS_ONLY; // copy lumps only, not the whole message - unsigned int new_buf_offs=0, orig_offs = 0; - char *hdr_lumps = NULL; - char *bdy_lumps = NULL; - const char *start_txt = "------------------------- START OF SIP message debug --------------------------\n"; - const char *hdr_txt = "------------------------------ SIP header diffs -------------------------------\n"; - const char *bdy_txt = "------------------------------- SIP body diffs --------------------------------\n"; - const char *end_txt = "-------------------------- END OF SIP message debug ---------------------------\n\n"; - struct dest_info send_info; - str obuf; - - if (level != NULL) { - /* substract L_OFFSET previously added */ - ilevel = (int)(long)level - L_OFFSET; - } - - if (facility != NULL) { - ifacility = (int)(long)facility; - } - - /* msg_apply_changes_f code needed to get the current msg */ - init_dest_info(&send_info); - send_info.proto = PROTO_UDP; - if(msg->first_line.type == SIP_REPLY) { - obuf.s = generate_res_buf_from_sip_res(msg, - (unsigned int*)&obuf.len, BUILD_NO_VIA1_UPDATE); - } else { - obuf.s = build_req_buf_from_sip_req(msg, - (unsigned int*)&obuf.len, &send_info, - BUILD_NO_PATH|BUILD_NO_LOCAL_VIA|BUILD_NO_VIA1_UPDATE); - } - - if(obuf.s == NULL) - { - LM_ERR("couldn't update msg buffer content\n"); - return -1; - } - - if(obuf.len >= BUF_SIZE) - { - LM_ERR("new buffer overflow (%d)\n", obuf.len); - pkg_free(obuf.s); - return -1; - } - - /* skip original uri */ - if (msg->new_uri.s){ - orig_offs=msg->first_line.u.request.uri.s - msg->buf; - orig_offs=msg->first_line.u.request.uri.len; - } - - /* alloc private mem and copy lumps */ - hdr_lumps = pkg_malloc(BUF_SIZE); - bdy_lumps = pkg_malloc(BUF_SIZE); - - new_buf_offs = 0; - process_lumps(msg, msg->add_rm, hdr_lumps, &new_buf_offs, &orig_offs, &send_info, flag); - - new_buf_offs = 0; - process_lumps(msg, msg->body_lumps, bdy_lumps, &new_buf_offs, &orig_offs, &send_info, flag); + int ilevel = cfg_get(core, core_cfg, debug); + int ifacility= cfg_get(core, core_cfg, log_facility); + int flag = FLAG_MSG_LUMPS_ONLY; // copy lumps only, not the whole message + unsigned int new_buf_offs=0, orig_offs = 0; + char *hdr_lumps = NULL; + char *bdy_lumps = NULL; + const char *start_txt = "------------------------- START OF SIP message debug --------------------------\n"; + const char *hdr_txt = "------------------------------ SIP header diffs -------------------------------\n"; + const char *bdy_txt = "------------------------------- SIP body diffs --------------------------------\n"; + const char *end_txt = "-------------------------- END OF SIP message debug ---------------------------\n\n"; + struct dest_info send_info; + str obuf; + + if (level != NULL) { + /* substract L_OFFSET previously added */ + ilevel = (int)(long)level - L_OFFSET; + } + + if (facility != NULL) { + ifacility = (int)(long)facility; + } + + /* msg_apply_changes_f code needed to get the current msg */ + init_dest_info(&send_info); + send_info.proto = PROTO_UDP; + if(msg->first_line.type == SIP_REPLY) { + obuf.s = generate_res_buf_from_sip_res(msg, + (unsigned int*)&obuf.len, BUILD_NO_VIA1_UPDATE); + } else { + obuf.s = build_req_buf_from_sip_req(msg, + (unsigned int*)&obuf.len, &send_info, + BUILD_NO_PATH|BUILD_NO_LOCAL_VIA|BUILD_NO_VIA1_UPDATE); + } + + if(obuf.s == NULL) + { + LM_ERR("couldn't update msg buffer content\n"); + return -1; + } + + if(obuf.len >= BUF_SIZE) + { + LM_ERR("new buffer overflow (%d)\n", obuf.len); + pkg_free(obuf.s); + return -1; + } + + /* skip original uri */ + if (msg->new_uri.s){ + orig_offs=msg->first_line.u.request.uri.s - msg->buf; + orig_offs=msg->first_line.u.request.uri.len; + } + + /* alloc private mem and copy lumps */ + hdr_lumps = pkg_malloc(BUF_SIZE); + bdy_lumps = pkg_malloc(BUF_SIZE); + + new_buf_offs = 0; + process_lumps(msg, msg->add_rm, hdr_lumps, &new_buf_offs, &orig_offs, &send_info, flag); + + new_buf_offs = 0; + process_lumps(msg, msg->body_lumps, bdy_lumps, &new_buf_offs, &orig_offs, &send_info, flag); /* do the print */ if (_dbg_sip_msg_cline < 0 ) { LOG_FC(ifacility, ilevel, "CONFIG LINE unknown\n%s%.*s%s%s%s%s%s", - start_txt, - obuf.len, obuf.s, - hdr_txt, hdr_lumps, - bdy_txt, bdy_lumps, - end_txt); + start_txt, + obuf.len, obuf.s, + hdr_txt, hdr_lumps, + bdy_txt, bdy_lumps, + end_txt); } else { LOG_FC(ifacility, ilevel, "CONFIG LINE %d\n%s%.*s%s%s%s%s%s", - _dbg_sip_msg_cline, - start_txt, - obuf.len, obuf.s, - hdr_txt, hdr_lumps, - bdy_txt, bdy_lumps, - end_txt); + _dbg_sip_msg_cline, + start_txt, + obuf.len, obuf.s, + hdr_txt, hdr_lumps, + bdy_txt, bdy_lumps, + end_txt); } - /* free lumps */ - if (hdr_lumps) { - pkg_free(hdr_lumps); - } + /* free lumps */ + if (hdr_lumps) { + pkg_free(hdr_lumps); + } - if (bdy_lumps) { - pkg_free(bdy_lumps); - } + if (bdy_lumps) { + pkg_free(bdy_lumps); + } - return 1; + return 1; } From 7b67ab4623f63cbf823be47a35135ba052278c9e Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Fri, 15 Jan 2016 10:55:49 +0200 Subject: [PATCH 117/142] debugger: Restrict dbg_sip_msg() to REQUEST/ONSEND Allow dbg_sip_msg only from REQUEST/ONSEND route in a similar way as for msg_apply_changes(). --- modules/debugger/debugger_mod.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/debugger/debugger_mod.c b/modules/debugger/debugger_mod.c index 9f8186d5259..768158616f0 100644 --- a/modules/debugger/debugger_mod.c +++ b/modules/debugger/debugger_mod.c @@ -99,11 +99,11 @@ static cmd_export_t cmds[]={ {"dbg_pv_dump", (cmd_function)w_dbg_dump, 2, fixup_dbg_pv_dump, 0, ANY_ROUTE}, {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 0, - fixup_dbg_sip_msg, 0, REQUEST_ROUTE}, + fixup_dbg_sip_msg, 0, REQUEST_ROUTE|ONREPLY_ROUTE}, {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 1, - fixup_dbg_sip_msg, 0, REQUEST_ROUTE}, + fixup_dbg_sip_msg, 0, REQUEST_ROUTE|ONREPLY_ROUTE}, {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 2, - fixup_dbg_sip_msg, 0, REQUEST_ROUTE}, + fixup_dbg_sip_msg, 0, REQUEST_ROUTE|ONREPLY_ROUTE}, {0, 0, 0, 0, 0, 0} }; @@ -777,6 +777,11 @@ static int w_dbg_sip_msg(struct sip_msg* msg, char *level, char *facility) struct dest_info send_info; str obuf; + if (msg->first_line.type != SIP_REPLY && get_route_type() != REQUEST_ROUTE) { + LM_ERR("invalid usage - not in request route\n"); + return -1; + } + if (level != NULL) { /* substract L_OFFSET previously added */ ilevel = (int)(long)level - L_OFFSET; From 5a2c0437693cd2ee08290892d15c8b64a8003784 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Fri, 15 Jan 2016 14:10:48 +0200 Subject: [PATCH 118/142] debugger: Update doku Document why debugger module should be loaded first in the module sequence. --- modules/debugger/doc/debugger_admin.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/debugger/doc/debugger_admin.xml b/modules/debugger/doc/debugger_admin.xml index d0f3511c0cb..0c9663211b4 100644 --- a/modules/debugger/doc/debugger_admin.xml +++ b/modules/debugger/doc/debugger_admin.xml @@ -57,6 +57,10 @@ + + NOTE: Due to the debugger module child_init() function, one should load the module first in the module sequence in order to initialize _dbg_pid_list. + Otherwise, another module (i.e. p_usrloc) forking a process with rank != PROC_INIT will fail. +
External Libraries or Applications From ee20f55a16e5015dd6e3ac76c318131240de6688 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 18 Jan 2016 08:41:42 +0100 Subject: [PATCH 119/142] uac: reg - auth proxy address can be updated upon account refresh --- modules/uac/uac_reg.c | 44 +++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/modules/uac/uac_reg.c b/modules/uac/uac_reg.c index 39499b69556..f614b3349c2 100644 --- a/modules/uac/uac_reg.c +++ b/modules/uac/uac_reg.c @@ -51,6 +51,8 @@ #define UAC_REG_GC_INTERVAL 150 #define UAC_REG_MAX_PASSWD_SIZE 63 +#define UAC_REG_MAX_URI_SIZE 127 + typedef struct _reg_uac { unsigned int h_uuid; @@ -471,13 +473,13 @@ int reg_ht_add_byuser(reg_uac_t *reg) return 0; } -#define reg_copy_shm(dst, src) do { \ +#define reg_copy_shm(dst, src, bsize) do { \ if((src)->s!=NULL) { \ (dst)->s = p; \ strncpy((dst)->s, (src)->s, (src)->len); \ (dst)->len = (src)->len; \ (dst)->s[(dst)->len] = '\0'; \ - p = p + (dst)->len + 1; \ + p = p + ((bsize)?(bsize):(dst)->len) + 1; \ } \ } while(0); @@ -501,6 +503,12 @@ int reg_ht_add(reg_uac_t *reg) reg, _reg_htable, reg->auth_password.len); return -1; } + if(reg->auth_proxy.len>UAC_REG_MAX_URI_SIZE) + { + LM_ERR("bad parameters: %p/%p -- proxy uri too long %d\n", + reg, _reg_htable, reg->auth_proxy.len); + return -1; + } len = reg->l_uuid.len + 1 + reg->l_username.len + 1 @@ -508,7 +516,7 @@ int reg_ht_add(reg_uac_t *reg) + reg->r_username.len + 1 + reg->r_domain.len + 1 + reg->realm.len + 1 - + reg->auth_proxy.len + 1 + + UAC_REG_MAX_URI_SIZE /*reg->auth_proxy.len*/ + 1 + reg->auth_username.len + 1 + UAC_REG_MAX_PASSWD_SIZE /*reg->auth_password.len*/ + 1; nr = (reg_uac_t*)shm_malloc(sizeof(reg_uac_t) + len); @@ -524,16 +532,16 @@ int reg_ht_add(reg_uac_t *reg) p = (char*)nr + sizeof(reg_uac_t); - reg_copy_shm(&nr->l_uuid, ®->l_uuid); - reg_copy_shm(&nr->l_username, ®->l_username); - reg_copy_shm(&nr->l_domain, ®->l_domain); - reg_copy_shm(&nr->r_username, ®->r_username); - reg_copy_shm(&nr->r_domain, ®->r_domain); - reg_copy_shm(&nr->realm, ®->realm); - reg_copy_shm(&nr->auth_proxy, ®->auth_proxy); - reg_copy_shm(&nr->auth_username, ®->auth_username); + reg_copy_shm(&nr->l_uuid, ®->l_uuid, 0); + reg_copy_shm(&nr->l_username, ®->l_username, 0); + reg_copy_shm(&nr->l_domain, ®->l_domain, 0); + reg_copy_shm(&nr->r_username, ®->r_username, 0); + reg_copy_shm(&nr->r_domain, ®->r_domain, 0); + reg_copy_shm(&nr->realm, ®->realm, 0); + reg_copy_shm(&nr->auth_proxy, ®->auth_proxy, UAC_REG_MAX_URI_SIZE); + reg_copy_shm(&nr->auth_username, ®->auth_username, 0); /* password at the end, to be able to update it easily */ - reg_copy_shm(&nr->auth_password, ®->auth_password); + reg_copy_shm(&nr->auth_password, ®->auth_password, 0); reg_ht_add_byuser(nr); reg_ht_add_byuuid(nr); @@ -546,7 +554,7 @@ int reg_ht_add(reg_uac_t *reg) /** * */ -int reg_ht_update_password(reg_uac_t *reg) +int reg_ht_update_attrs(reg_uac_t *reg) { unsigned int slot; reg_item_t *ri = NULL; @@ -562,6 +570,11 @@ int reg_ht_update_password(reg_uac_t *reg) LM_ERR("password is too big: %d\n", reg->auth_password.len); return -1; } + if(reg->auth_proxy.len>UAC_REG_MAX_URI_SIZE) + { + LM_ERR("proxy uri is too big: %d\n", reg->auth_proxy.len); + return -1; + } slot = reg_get_entry(reg->h_user, _reg_htable->htsize); lock_get(&_reg_htable->entries[slot].lock); @@ -574,6 +587,9 @@ int reg_ht_update_password(reg_uac_t *reg) strncpy(ri->r->auth_password.s, reg->auth_password.s, reg->auth_password.len); ri->r->auth_password.len = reg->auth_password.len; ri->r->auth_password.s[reg->auth_password.len] = '\0'; + strncpy(ri->r->auth_proxy.s, reg->auth_proxy.s, reg->auth_proxy.len); + ri->r->auth_proxy.len = reg->auth_proxy.len; + ri->r->auth_proxy.s[reg->auth_proxy.len] = '\0'; lock_release(&_reg_htable->entries[slot].lock); return 0; } @@ -1288,7 +1304,7 @@ int uac_reg_db_refresh(str *pl_uuid) lock_get(_reg_htable_gc_lock); if(reg_ht_get_byuuid(pl_uuid)!=NULL) { - if(reg_ht_update_password(®)<0) + if(reg_ht_update_attrs(®)<0) { lock_release(_reg_htable_gc_lock); LM_ERR("Error updating reg to htable\n"); From c0166c037a9db4d0cc90e335541ea7b24add4768 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 18 Jan 2016 09:05:39 +0100 Subject: [PATCH 120/142] lib/srdb1: uacreg table has two new columns - flags, reg_delay - store the flags for runtime behavior - delay intial registration (allow to spread registrations over an interval of time, not to flood the registrar at the same time) --- lib/srdb1/schema/uacreg.xml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/srdb1/schema/uacreg.xml b/lib/srdb1/schema/uacreg.xml index 7f690b6a3bb..18baeffcd65 100644 --- a/lib/srdb1/schema/uacreg.xml +++ b/lib/srdb1/schema/uacreg.xml @@ -9,7 +9,7 @@ uacreg - 1 + 2&MYSQL_TABLE_TYPE; This table is used by theuac module to load user details for remote server registration: &KAMAILIO_MOD_DOC;uac.html @@ -105,6 +105,20 @@ Expiration time (in seconds, 0 means disabled) + + flags + int + 0 + Flags to control the behavior + + + + reg_delay + int + 0 + Initial registration delay + + l_uuid_idx From 8fb9f17154ab17c41091b9d71b13b3089b79338a Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 18 Jan 2016 09:07:40 +0100 Subject: [PATCH 121/142] kamctl: updated db definition scripts for uacreg table --- utils/kamctl/db_berkeley/kamailio/uacreg | 4 ++-- utils/kamctl/db_berkeley/kamailio/version | 2 +- utils/kamctl/db_sqlite/uac-create.sql | 4 +++- utils/kamctl/dbtext/kamailio/uacreg | 2 +- utils/kamctl/dbtext/kamailio/version | 2 +- utils/kamctl/mysql/uac-create.sql | 4 +++- utils/kamctl/oracle/uac-create.sql | 4 +++- utils/kamctl/postgres/uac-create.sql | 4 +++- utils/kamctl/xhttp_pi/pi_framework.xml | 8 ++++++++ utils/kamctl/xhttp_pi/uac-mod | 6 ++++++ utils/kamctl/xhttp_pi/uac-table | 2 ++ 11 files changed, 33 insertions(+), 9 deletions(-) diff --git a/utils/kamctl/db_berkeley/kamailio/uacreg b/utils/kamctl/db_berkeley/kamailio/uacreg index 7dda496e923..1468d8e768e 100644 --- a/utils/kamctl/db_berkeley/kamailio/uacreg +++ b/utils/kamctl/db_berkeley/kamailio/uacreg @@ -1,5 +1,5 @@ METADATA_COLUMNS -id(int) l_uuid(str) l_username(str) l_domain(str) r_username(str) r_domain(str) realm(str) auth_username(str) auth_password(str) auth_proxy(str) expires(int) +id(int) l_uuid(str) l_username(str) l_domain(str) r_username(str) r_domain(str) realm(str) auth_username(str) auth_password(str) auth_proxy(str) expires(int) flags(int) reg_delay(int) METADATA_KEY METADATA_READONLY @@ -7,4 +7,4 @@ METADATA_READONLY METADATA_LOGFLAGS 0 METADATA_DEFAULTS -NIL|''|''|''|''|''|''|''|''|''|0 +NIL|''|''|''|''|''|''|''|''|''|0|0|0 diff --git a/utils/kamctl/db_berkeley/kamailio/version b/utils/kamctl/db_berkeley/kamailio/version index 5796a95e463..6f7e0eb4b09 100644 --- a/utils/kamctl/db_berkeley/kamailio/version +++ b/utils/kamctl/db_berkeley/kamailio/version @@ -117,7 +117,7 @@ subscriber|6 trusted| trusted|6 uacreg| -uacreg|1 +uacreg|2 uid_credentials| uid_credentials|7 uid_domain| diff --git a/utils/kamctl/db_sqlite/uac-create.sql b/utils/kamctl/db_sqlite/uac-create.sql index 991f358aeb7..4df6b0249cd 100644 --- a/utils/kamctl/db_sqlite/uac-create.sql +++ b/utils/kamctl/db_sqlite/uac-create.sql @@ -10,8 +10,10 @@ CREATE TABLE uacreg ( auth_password VARCHAR(64) DEFAULT '' NOT NULL, auth_proxy VARCHAR(64) DEFAULT '' NOT NULL, expires INTEGER DEFAULT 0 NOT NULL, + flags INTEGER DEFAULT 0 NOT NULL, + reg_delay INTEGER DEFAULT 0 NOT NULL, CONSTRAINT uacreg_l_uuid_idx UNIQUE (l_uuid) ); -INSERT INTO version (table_name, table_version) values ('uacreg','1'); +INSERT INTO version (table_name, table_version) values ('uacreg','2'); diff --git a/utils/kamctl/dbtext/kamailio/uacreg b/utils/kamctl/dbtext/kamailio/uacreg index 1fddd284b3b..d69829903b5 100644 --- a/utils/kamctl/dbtext/kamailio/uacreg +++ b/utils/kamctl/dbtext/kamailio/uacreg @@ -1 +1 @@ -id(int,auto) l_uuid(string) l_username(string) l_domain(string) r_username(string) r_domain(string) realm(string) auth_username(string) auth_password(string) auth_proxy(string) expires(int) +id(int,auto) l_uuid(string) l_username(string) l_domain(string) r_username(string) r_domain(string) realm(string) auth_username(string) auth_password(string) auth_proxy(string) expires(int) flags(int) reg_delay(int) diff --git a/utils/kamctl/dbtext/kamailio/version b/utils/kamctl/dbtext/kamailio/version index adcfd00d450..465b86356b4 100644 --- a/utils/kamctl/dbtext/kamailio/version +++ b/utils/kamctl/dbtext/kamailio/version @@ -53,7 +53,7 @@ sip_trace:4 speed_dial:2 subscriber:6 trusted:6 -uacreg:1 +uacreg:2 uid_credentials:7 uid_domain:2 uid_domain_attrs:1 diff --git a/utils/kamctl/mysql/uac-create.sql b/utils/kamctl/mysql/uac-create.sql index a7e84645d95..952c6bfb1f6 100644 --- a/utils/kamctl/mysql/uac-create.sql +++ b/utils/kamctl/mysql/uac-create.sql @@ -10,8 +10,10 @@ CREATE TABLE `uacreg` ( `auth_password` VARCHAR(64) DEFAULT '' NOT NULL, `auth_proxy` VARCHAR(64) DEFAULT '' NOT NULL, `expires` INT DEFAULT 0 NOT NULL, + `flags` INT DEFAULT 0 NOT NULL, + `reg_delay` INT DEFAULT 0 NOT NULL, CONSTRAINT l_uuid_idx UNIQUE (`l_uuid`) ); -INSERT INTO version (table_name, table_version) values ('uacreg','1'); +INSERT INTO version (table_name, table_version) values ('uacreg','2'); diff --git a/utils/kamctl/oracle/uac-create.sql b/utils/kamctl/oracle/uac-create.sql index 93d6dac4e98..88381cb1b11 100644 --- a/utils/kamctl/oracle/uac-create.sql +++ b/utils/kamctl/oracle/uac-create.sql @@ -10,6 +10,8 @@ CREATE TABLE uacreg ( auth_password VARCHAR2(64) DEFAULT '', auth_proxy VARCHAR2(64) DEFAULT '', expires NUMBER(10) DEFAULT 0 NOT NULL, + flags NUMBER(10) DEFAULT 0 NOT NULL, + reg_delay NUMBER(10) DEFAULT 0 NOT NULL, CONSTRAINT uacreg_l_uuid_idx UNIQUE (l_uuid) ); @@ -21,5 +23,5 @@ END uacreg_tr; / BEGIN map2users('uacreg'); END; / -INSERT INTO version (table_name, table_version) values ('uacreg','1'); +INSERT INTO version (table_name, table_version) values ('uacreg','2'); diff --git a/utils/kamctl/postgres/uac-create.sql b/utils/kamctl/postgres/uac-create.sql index 3c67e4ba95c..5c6078610d0 100644 --- a/utils/kamctl/postgres/uac-create.sql +++ b/utils/kamctl/postgres/uac-create.sql @@ -10,8 +10,10 @@ CREATE TABLE uacreg ( auth_password VARCHAR(64) DEFAULT '' NOT NULL, auth_proxy VARCHAR(64) DEFAULT '' NOT NULL, expires INTEGER DEFAULT 0 NOT NULL, + flags INTEGER DEFAULT 0 NOT NULL, + reg_delay INTEGER DEFAULT 0 NOT NULL, CONSTRAINT uacreg_l_uuid_idx UNIQUE (l_uuid) ); -INSERT INTO version (table_name, table_version) values ('uacreg','1'); +INSERT INTO version (table_name, table_version) values ('uacreg','2'); diff --git a/utils/kamctl/xhttp_pi/pi_framework.xml b/utils/kamctl/xhttp_pi/pi_framework.xml index 367fb9f6746..82908d2cae4 100644 --- a/utils/kamctl/xhttp_pi/pi_framework.xml +++ b/utils/kamctl/xhttp_pi/pi_framework.xml @@ -752,6 +752,8 @@ auth_passwordDB1_STR auth_proxyDB1_STR expiresDB1_INT + flagsDB1_INT + reg_delayDB1_INT @@ -3806,6 +3808,8 @@ auth_passwordauth_proxyexpires + flags + reg_delayadd @@ -3822,6 +3826,8 @@ auth_passwordauth_proxyexpires + flags + reg_delayupdate @@ -3841,6 +3847,8 @@ auth_passwordauth_proxyexpires + flags + reg_delaydelete diff --git a/utils/kamctl/xhttp_pi/uac-mod b/utils/kamctl/xhttp_pi/uac-mod index 8b39119f21f..6dfcf1e7d2f 100644 --- a/utils/kamctl/xhttp_pi/uac-mod +++ b/utils/kamctl/xhttp_pi/uac-mod @@ -15,6 +15,8 @@ auth_passwordauth_proxyexpires + flags + reg_delayadd @@ -31,6 +33,8 @@ auth_passwordauth_proxyexpires + flags + reg_delayupdate @@ -50,6 +54,8 @@ auth_passwordauth_proxyexpires + flags + reg_delaydelete diff --git a/utils/kamctl/xhttp_pi/uac-table b/utils/kamctl/xhttp_pi/uac-table index 2ba08bfb82d..dad33ccf13d 100644 --- a/utils/kamctl/xhttp_pi/uac-table +++ b/utils/kamctl/xhttp_pi/uac-table @@ -13,4 +13,6 @@ auth_passwordDB1_STR auth_proxyDB1_STR expiresDB1_INT + flagsDB1_INT + reg_delayDB1_INT From b711cb98b4111c4f1d7fe73ed005fd54e2634696 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 18 Jan 2016 09:08:20 +0100 Subject: [PATCH 122/142] uac: load flags column from database - related to GH #369 --- modules/uac/uac_reg.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/modules/uac/uac_reg.c b/modules/uac/uac_reg.c index f614b3349c2..cadc47396bf 100644 --- a/modules/uac/uac_reg.c +++ b/modules/uac/uac_reg.c @@ -69,6 +69,7 @@ typedef struct _reg_uac unsigned int flags; unsigned int expires; time_t timer_expires; + unsigned int reg_delay; } reg_uac_t; typedef struct _reg_item @@ -117,6 +118,8 @@ str auth_username_column = str_init("auth_username"); str auth_password_column = str_init("auth_password"); str auth_proxy_column = str_init("auth_proxy"); str expires_column = str_init("expires"); +str flags_column = str_init("flags"); +str reg_delay_column = str_init("reg_delay"); #if 0 @@ -133,6 +136,8 @@ CREATE TABLE uacreg ( auth_password VARCHAR(64) NOT NULL, auth_proxy VARCHAR(128) DEFAULT '' NOT NULL, expires INT(10) UNSIGNED DEFAULT 0 NOT NULL, + flags INT(10) UNSIGNED DEFAULT 0 NOT NULL, + reg_delay INT(10) UNSIGNED DEFAULT 0 NOT NULL, CONSTRAINT l_uuid_idx UNIQUE (l_uuid) ) ENGINE=MyISAM; #endif @@ -1071,7 +1076,7 @@ int uac_reg_load_db(void) db1_con_t *reg_db_con = NULL; db_func_t reg_dbf; reg_uac_t reg; - db_key_t db_cols[10] = { + db_key_t db_cols[12] = { &l_uuid_column, &l_username_column, &l_domain_column, @@ -1081,7 +1086,9 @@ int uac_reg_load_db(void) &auth_username_column, &auth_password_column, &auth_proxy_column, - &expires_column + &expires_column, + &flags_column, + ®_delay_column }; db1_res_t* db_res = NULL; int i, ret; @@ -1120,7 +1127,7 @@ int uac_reg_load_db(void) } if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) { - if(reg_dbf.query(reg_db_con, 0, 0, 0, db_cols, 0, 10, 0, 0) < 0) + if(reg_dbf.query(reg_db_con, 0, 0, 0, db_cols, 0, 12, 0, 0) < 0) { LM_ERR("Error while querying db\n"); return -1; @@ -1172,6 +1179,10 @@ int uac_reg_load_db(void) reg_db_set_attr(auth_proxy, 8); reg.expires = (unsigned int)RES_ROWS(db_res)[i].values[9].val.int_val; + reg.flags + = (unsigned int)RES_ROWS(db_res)[i].values[10].val.int_val; + reg.reg_delay + = (unsigned int)RES_ROWS(db_res)[i].values[11].val.int_val; if(reg_ht_add(®)<0) { @@ -1212,7 +1223,7 @@ int uac_reg_db_refresh(str *pl_uuid) db1_con_t *reg_db_con = NULL; db_func_t reg_dbf; reg_uac_t reg; - db_key_t db_cols[10] = { + db_key_t db_cols[12] = { &l_uuid_column, &l_username_column, &l_domain_column, @@ -1222,7 +1233,9 @@ int uac_reg_db_refresh(str *pl_uuid) &auth_username_column, &auth_password_column, &auth_proxy_column, - &expires_column + &expires_column, + &flags_column, + ®_delay_column }; db_key_t db_keys[1] = {&l_uuid_column}; db_val_t db_vals[1]; @@ -1269,7 +1282,7 @@ int uac_reg_db_refresh(str *pl_uuid) db_vals[0].val.str_val.len = pl_uuid->len; if((ret=reg_dbf.query(reg_db_con, db_keys, NULL, db_vals, db_cols, - 1 /*nr keys*/, 10 /*nr cols*/, 0, &db_res))!=0 + 1 /*nr keys*/, 12 /*nr cols*/, 0, &db_res))!=0 || RES_ROW_N(db_res)<=0 ) { reg_dbf.free_result(reg_db_con, db_res); @@ -1300,6 +1313,8 @@ int uac_reg_db_refresh(str *pl_uuid) reg.expires = (unsigned int)RES_ROWS(db_res)[i].values[9].val.int_val; reg.h_uuid = reg_compute_hash(®.l_uuid); reg.h_user = reg_compute_hash(®.l_username); + reg.flags = (unsigned int)RES_ROWS(db_res)[i].values[10].val.int_val; + reg.reg_delay = (unsigned int)RES_ROWS(db_res)[i].values[11].val.int_val; lock_get(_reg_htable_gc_lock); if(reg_ht_get_byuuid(pl_uuid)!=NULL) @@ -1508,7 +1523,7 @@ static void rpc_uac_reg_dump(rpc_t* rpc, void* ctx) rpc->fault(ctx, 500, "Internal error creating rpc"); return; } - if(rpc->struct_add(th, "SSSSSSSSSdddd", + if(rpc->struct_add(th, "SSSSSSSSSddddd", "l_uuid", ®->r->l_uuid, "l_username", ®->r->l_username, "l_domain", ®->r->l_domain, @@ -1522,7 +1537,8 @@ static void rpc_uac_reg_dump(rpc_t* rpc, void* ctx) "expires", (int)reg->r->expires, "flags", (int)reg->r->flags, "diff_expires", (int)(reg->r->timer_expires - tn), - "timer_expires", (int)reg->r->timer_expires + "timer_expires", (int)reg->r->timer_expires, + "reg_delay", (int)reg->r->reg_delay )<0) { lock_release(&_reg_htable->entries[i].lock); From 5b9c5b7dfac1aa7eb98e7986fd3345e3f411783a Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 18 Jan 2016 09:15:37 +0100 Subject: [PATCH 123/142] uac: update flags for disabled state when refreshing record from db --- modules/uac/uac_reg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/uac/uac_reg.c b/modules/uac/uac_reg.c index cadc47396bf..509d2ef4484 100644 --- a/modules/uac/uac_reg.c +++ b/modules/uac/uac_reg.c @@ -532,6 +532,8 @@ int reg_ht_add(reg_uac_t *reg) } memset(nr, 0, sizeof(reg_uac_t) + len); nr->expires = reg->expires; + nr->flags = reg->flags; + nr->reg_delay = reg->reg_delay; nr->h_uuid = reg_compute_hash(®->l_uuid); nr->h_user = reg_compute_hash(®->l_username); @@ -595,6 +597,7 @@ int reg_ht_update_attrs(reg_uac_t *reg) strncpy(ri->r->auth_proxy.s, reg->auth_proxy.s, reg->auth_proxy.len); ri->r->auth_proxy.len = reg->auth_proxy.len; ri->r->auth_proxy.s[reg->auth_proxy.len] = '\0'; + if(reg->flags & UAC_REG_DISABLED) ri->r->flags |= UAC_REG_DISABLED; lock_release(&_reg_htable->entries[slot].lock); return 0; } From 7466ec937e50d274ec032d37f7de26eee1418625 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 18 Jan 2016 10:03:28 +0100 Subject: [PATCH 124/142] uac: support for initial delay of registration - delay initial registration with at least reg_delay value from uacreg table --- modules/uac/uac_reg.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/modules/uac/uac_reg.c b/modules/uac/uac_reg.c index 509d2ef4484..b3ad81964ae 100644 --- a/modules/uac/uac_reg.c +++ b/modules/uac/uac_reg.c @@ -46,6 +46,7 @@ #define UAC_REG_ONGOING (1<<1) #define UAC_REG_ONLINE (1<<2) #define UAC_REG_AUTHSENT (1<<3) +#define UAC_REG_INIT (1<<4) #define MAX_UACH_SIZE 2048 #define UAC_REG_GC_INTERVAL 150 @@ -70,6 +71,7 @@ typedef struct _reg_uac unsigned int expires; time_t timer_expires; unsigned int reg_delay; + time_t reg_init; } reg_uac_t; typedef struct _reg_item @@ -534,6 +536,7 @@ int reg_ht_add(reg_uac_t *reg) nr->expires = reg->expires; nr->flags = reg->flags; nr->reg_delay = reg->reg_delay; + nr->reg_init = time(NULL); nr->h_uuid = reg_compute_hash(®->l_uuid); nr->h_user = reg_compute_hash(®->l_username); @@ -961,6 +964,16 @@ int uac_reg_update(reg_uac_t *reg, time_t tn) } if(reg->flags&UAC_REG_DISABLED) return 4; + + if(!(reg->flags & UAC_REG_INIT)) { + if(reg->reg_delay>0) { + if(tn < reg->reg_init+reg->reg_delay) { + return 2; + } + } + } + reg->flags |= UAC_REG_INIT; + if(reg->timer_expires > tn + reg_timer_interval + 3) return 3; uuid = (char*)shm_malloc(reg->l_uuid.len+1); @@ -1526,7 +1539,7 @@ static void rpc_uac_reg_dump(rpc_t* rpc, void* ctx) rpc->fault(ctx, 500, "Internal error creating rpc"); return; } - if(rpc->struct_add(th, "SSSSSSSSSddddd", + if(rpc->struct_add(th, "SSSSSSSSSdddddd", "l_uuid", ®->r->l_uuid, "l_username", ®->r->l_username, "l_domain", ®->r->l_domain, @@ -1541,6 +1554,7 @@ static void rpc_uac_reg_dump(rpc_t* rpc, void* ctx) "flags", (int)reg->r->flags, "diff_expires", (int)(reg->r->timer_expires - tn), "timer_expires", (int)reg->r->timer_expires, + "reg_init", (int)reg->r->reg_init, "reg_delay", (int)reg->r->reg_delay )<0) { From feb8c87d48041f59d71699e6fb7da5e47b325532 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 18 Jan 2016 10:35:42 +0100 Subject: [PATCH 125/142] uac: coherent indentation for uac reg code --- modules/uac/uac.c | 52 ++++++------ modules/uac/uac_reg.c | 190 +++++++++++++++++++++--------------------- 2 files changed, 121 insertions(+), 121 deletions(-) diff --git a/modules/uac/uac.c b/modules/uac/uac.c index 125b08b2c0b..eada8581069 100644 --- a/modules/uac/uac.c +++ b/modules/uac/uac.c @@ -102,21 +102,21 @@ static pv_export_t mod_pvs[] = { /* Exported functions */ static cmd_export_t cmds[]={ {"uac_replace_from", (cmd_function)w_replace_from, 2, fixup_replace_uri, 0, - REQUEST_ROUTE | BRANCH_ROUTE }, + REQUEST_ROUTE | BRANCH_ROUTE }, {"uac_replace_from", (cmd_function)w_replace_from, 1, fixup_replace_uri, 0, - REQUEST_ROUTE | BRANCH_ROUTE }, + REQUEST_ROUTE | BRANCH_ROUTE }, {"uac_restore_from", (cmd_function)w_restore_from, 0, 0, 0, - REQUEST_ROUTE }, + REQUEST_ROUTE }, {"uac_replace_to", (cmd_function)w_replace_to, 2, fixup_replace_uri, 0, - REQUEST_ROUTE | BRANCH_ROUTE }, + REQUEST_ROUTE | BRANCH_ROUTE }, {"uac_replace_to", (cmd_function)w_replace_to, 1, fixup_replace_uri, 0, - REQUEST_ROUTE | BRANCH_ROUTE }, + REQUEST_ROUTE | BRANCH_ROUTE }, {"uac_restore_to", (cmd_function)w_restore_to, 0, 0, 0, - REQUEST_ROUTE }, + REQUEST_ROUTE }, {"uac_auth", (cmd_function)w_uac_auth, 0, 0, 0, - FAILURE_ROUTE }, + FAILURE_ROUTE }, {"uac_req_send", (cmd_function)w_uac_req_send, 0, 0, 0, - ANY_ROUTE}, + ANY_ROUTE}, {"uac_reg_lookup", (cmd_function)w_uac_reg_lookup, 2, fixup_pvar_pvar, fixup_free_pvar_pvar, ANY_ROUTE }, {"uac_reg_request_to", (cmd_function)w_uac_reg_request_to, 2, fixup_pvar_uint, fixup_free_pvar_uint, @@ -144,8 +144,8 @@ static param_export_t params[] = { {"reg_db_url", PARAM_STR, ®_db_url }, {"reg_db_table", PARAM_STR, ®_db_table }, {"reg_contact_addr", PARAM_STR, ®_contact_addr }, - {"reg_timer_interval", INT_PARAM, ®_timer_interval }, - {"reg_retry_interval",INT_PARAM, ®_retry_interval }, + {"reg_timer_interval", INT_PARAM, ®_timer_interval }, + {"reg_retry_interval", INT_PARAM, ®_retry_interval }, {0, 0, 0} }; @@ -185,10 +185,10 @@ static int mod_init(void) if (restore_mode_str && *restore_mode_str) { if (strcasecmp(restore_mode_str,"none")==0) { - restore_mode = UAC_NO_RESTORE; - } else if (strcasecmp(restore_mode_str,"manual")==0) { - restore_mode = UAC_MANUAL_RESTORE; - } else if (strcasecmp(restore_mode_str,"auto")==0) { + restore_mode = UAC_NO_RESTORE; + } else if (strcasecmp(restore_mode_str,"manual")==0) { + restore_mode = UAC_MANUAL_RESTORE; + } else if (strcasecmp(restore_mode_str,"auto")==0) { restore_mode = UAC_AUTO_RESTORE; } else { LM_ERR("unsupported value '%s' for restore_mode\n", restore_mode_str); @@ -209,9 +209,9 @@ static int mod_init(void) goto error; } if ( parse_auth_avp(auth_realm_avp, &auth_realm_spec, "realm")<0 - || parse_auth_avp(auth_username_avp, &auth_username_spec, "username")<0 - || parse_auth_avp(auth_password_avp, &auth_password_spec, "password")<0 - ) { + || parse_auth_avp(auth_username_avp, &auth_username_spec, "username")<0 + || parse_auth_avp(auth_password_avp, &auth_password_spec, "password")<0 + ) { goto error; } } else { @@ -275,7 +275,7 @@ static int mod_init(void) if (uac_restore_dlg==0 || load_dlg_api(&dlg_api)!=0) { if (!uac_rrb.append_fromtag) { LM_ERR("'append_fromtag' RR param is not enabled!" - " - required by AUTO restore mode\n"); + " - required by AUTO restore mode\n"); goto error; } if (uac_restore_dlg!=0) @@ -415,9 +415,9 @@ int w_replace_from(struct sip_msg* msg, char* p1, char* p2) str *dsp = NULL; if (p2==NULL) { - p2 = p1; - p1 = NULL; - dsp = NULL; + p2 = p1; + p1 = NULL; + dsp = NULL; } /* p1 display , p2 uri */ @@ -487,7 +487,7 @@ static int w_replace_to(struct sip_msg* msg, char* p1, char* p2) dsp = NULL; } - /* p1 display , p2 uri */ + /* p1 display , p2 uri */ if( p1!=NULL ) { if(pv_printf_s( msg, (pv_elem_p)p1, &dsp_s)!=0) @@ -553,8 +553,8 @@ static int w_uac_reg_lookup(struct sip_msg* msg, char* src, char* dst) if (!(val.flags & PV_VAL_STR)) { - LM_ERR("src pv value is not string\n"); - return -1; + LM_ERR("src pv value is not string\n"); + return -1; } return uac_reg_lookup(msg, &val.rs, dpv, 0); } @@ -577,8 +577,8 @@ static int w_uac_reg_request_to(struct sip_msg* msg, char* src, char* mode_s) if (!(val.flags & PV_VAL_STR)) { - LM_ERR("src pv value is not string\n"); - return -1; + LM_ERR("src pv value is not string\n"); + return -1; } if (mode > 1) diff --git a/modules/uac/uac_reg.c b/modules/uac/uac_reg.c index b3ad81964ae..c0cf6e8def4 100644 --- a/modules/uac/uac_reg.c +++ b/modules/uac/uac_reg.c @@ -127,21 +127,21 @@ str reg_delay_column = str_init("reg_delay"); #if 0 INSERT INTO version (table_name, table_version) values ('uacreg','1'); CREATE TABLE uacreg ( - id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL, - l_uuid VARCHAR(64) NOT NULL, - l_username VARCHAR(64) NOT NULL, - l_domain VARCHAR(128) DEFAULT '' NOT NULL, - r_username VARCHAR(64) NOT NULL, - r_domain VARCHAR(128) NOT NULL, - realm VARCHAR(64) NOT NULL, - auth_username VARCHAR(64) NOT NULL, - auth_password VARCHAR(64) NOT NULL, - auth_proxy VARCHAR(128) DEFAULT '' NOT NULL, - expires INT(10) UNSIGNED DEFAULT 0 NOT NULL, - flags INT(10) UNSIGNED DEFAULT 0 NOT NULL, - reg_delay INT(10) UNSIGNED DEFAULT 0 NOT NULL, - CONSTRAINT l_uuid_idx UNIQUE (l_uuid) -) ENGINE=MyISAM; + id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL, + l_uuid VARCHAR(64) NOT NULL, + l_username VARCHAR(64) NOT NULL, + l_domain VARCHAR(128) DEFAULT '' NOT NULL, + r_username VARCHAR(64) NOT NULL, + r_domain VARCHAR(128) NOT NULL, + realm VARCHAR(64) NOT NULL, + auth_username VARCHAR(64) NOT NULL, + auth_password VARCHAR(64) NOT NULL, + auth_proxy VARCHAR(128) DEFAULT '' NOT NULL, + expires INT(10) UNSIGNED DEFAULT 0 NOT NULL, + flags INT(10) UNSIGNED DEFAULT 0 NOT NULL, + reg_delay INT(10) UNSIGNED DEFAULT 0 NOT NULL, + CONSTRAINT l_uuid_idx UNIQUE (l_uuid) + ) ENGINE=MyISAM; #endif @@ -158,9 +158,9 @@ counter_handle_t regdisabled; /* Disabled registrations */ static void uac_reg_counter_init() { LM_DBG("*** Initializing UAC reg counters\n"); - counter_register(®total, "uac", "regtotal", 0, 0, 0, "Total number of registration accounts in memory", 0); - counter_register(®active, "uac", "regactive", 0, 0, 0, "Number of successfully registred accounts (200 OK)", 0); - counter_register(®disabled, "uac", "regdisabled", 0, 0, 0, "Counter of failed registrations (not 200 OK)", 0); + counter_register(®total, "uac", "regtotal", 0, 0, 0, "Total number of registration accounts in memory", 0); + counter_register(®active, "uac", "regactive", 0, 0, 0, "Number of successfully registred accounts (200 OK)", 0); + counter_register(®disabled, "uac", "regdisabled", 0, 0, 0, "Counter of failed registrations (not 200 OK)", 0); } @@ -195,7 +195,7 @@ int uac_reg_init_ht(unsigned int sz) _reg_htable_gc->htsize = sz; _reg_htable_gc->entries = - (reg_entry_t*)shm_malloc(_reg_htable_gc->htsize*sizeof(reg_entry_t)); + (reg_entry_t*)shm_malloc(_reg_htable_gc->htsize*sizeof(reg_entry_t)); if(_reg_htable_gc->entries==NULL) { LM_ERR("no more shm.\n"); @@ -221,7 +221,7 @@ int uac_reg_init_ht(unsigned int sz) _reg_htable->htsize = sz; _reg_htable->entries = - (reg_entry_t*)shm_malloc(_reg_htable->htsize*sizeof(reg_entry_t)); + (reg_entry_t*)shm_malloc(_reg_htable->htsize*sizeof(reg_entry_t)); if(_reg_htable->entries==NULL) { LM_ERR("no more shm.\n"); @@ -518,14 +518,14 @@ int reg_ht_add(reg_uac_t *reg) } len = reg->l_uuid.len + 1 - + reg->l_username.len + 1 - + reg->l_domain.len + 1 - + reg->r_username.len + 1 - + reg->r_domain.len + 1 - + reg->realm.len + 1 - + UAC_REG_MAX_URI_SIZE /*reg->auth_proxy.len*/ + 1 - + reg->auth_username.len + 1 - + UAC_REG_MAX_PASSWD_SIZE /*reg->auth_password.len*/ + 1; + + reg->l_username.len + 1 + + reg->l_domain.len + 1 + + reg->r_username.len + 1 + + reg->r_domain.len + 1 + + reg->realm.len + 1 + + UAC_REG_MAX_URI_SIZE /*reg->auth_proxy.len*/ + 1 + + reg->auth_username.len + 1 + + UAC_REG_MAX_PASSWD_SIZE /*reg->auth_password.len*/ + 1; nr = (reg_uac_t*)shm_malloc(sizeof(reg_uac_t) + len); if(nr==NULL) { @@ -539,7 +539,7 @@ int reg_ht_add(reg_uac_t *reg) nr->reg_init = time(NULL); nr->h_uuid = reg_compute_hash(®->l_uuid); nr->h_user = reg_compute_hash(®->l_username); - + p = (char*)nr + sizeof(reg_uac_t); reg_copy_shm(&nr->l_uuid, ®->l_uuid, 0); @@ -666,7 +666,7 @@ reg_uac_t *reg_ht_get_byuser(str *user, str *domain) if(domain!=NULL && domain->s!=NULL) { if((it->r->l_domain.len==domain->len) - && (strncmp(it->r->l_domain.s, domain->s, domain->len)==0)) + && (strncmp(it->r->l_domain.s, domain->s, domain->len)==0)) { return it->r; } @@ -747,7 +747,7 @@ void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps) } uuid = *((char**)ps->param); LM_DBG("completed with status %d [uuid: %s]\n", - ps->code, uuid); + ps->code, uuid); suuid.s = uuid; suuid.len = strlen(suuid.s); ri = reg_ht_get_byuuid(&suuid); @@ -830,7 +830,7 @@ void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps) } LM_DBG("auth header body [%.*s]\n", - hdr->body.len, hdr->body.s); + hdr->body.len, hdr->body.s); if (parse_authenticate_body(&hdr->body, &auth)<0) { @@ -843,14 +843,14 @@ void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps) || strncmp(auth.realm.s, ri->realm.s, ri->realm.len)!=0) { LM_ERR("realms do not match. requested realm: [%.*s]\n", - auth.realm.len, auth.realm.s); + auth.realm.len, auth.realm.s); goto error; } } cred.realm = auth.realm; cred.user = ri->auth_username; cred.passwd = ri->auth_password; - cred.next = NULL; + cred.next = NULL; snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s", ri->r_domain.len, ri->r_domain.s); @@ -858,13 +858,13 @@ void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps) do_uac_auth(&method, &s_ruri, &cred, &auth, response); new_auth_hdr=build_authorization_hdr(ps->code, &s_ruri, &cred, - &auth, response); + &auth, response); if (new_auth_hdr==0) { LM_ERR("failed to build authorization hdr\n"); goto error; } - + #ifdef UAC_OLD_AUTH snprintf(b_turi, MAX_URI_SIZE, "sip:%.*s@%.*s", ri->r_username.len, ri->r_username.s, @@ -905,13 +905,13 @@ void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps) &s_turi, /* To */ &s_turi, /* From */ (ri->auth_proxy.len)?&ri->auth_proxy:NULL /* outbound uri */ - ); + ); #endif ret = uac_tmb.t_request_within(&uac_r); if(ret<0) { LM_ERR("failed to send request with authentication for [%.*s]", - ri->l_uuid.len, ri->l_uuid.s); + ri->l_uuid.len, ri->l_uuid.s); goto error; } @@ -920,7 +920,7 @@ void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps) } else { LM_ERR("got sip response %d while registering [%.*s]\n", - ps->code, ri->l_uuid.len, ri->l_uuid.s); + ps->code, ri->l_uuid.len, ri->l_uuid.s); goto error; } @@ -1019,7 +1019,7 @@ int uac_reg_update(reg_uac_t *reg, time_t tn) &s_turi, /* To */ &s_turi, /* From */ (reg->auth_proxy.len)?®->auth_proxy:NULL /* outbound uri */ - ); + ); if(ret<0) { @@ -1072,17 +1072,17 @@ void uac_reg_timer(unsigned int ticks) } #define reg_db_set_attr(attr, pos) do { \ - if(!VAL_NULL(&RES_ROWS(db_res)[i].values[pos])) { \ - reg.attr.s = \ - (char*)(RES_ROWS(db_res)[i].values[pos].val.string_val); \ - reg.attr.len = strlen(reg.attr.s); \ - if(reg.attr.len == 0) { \ - LM_ERR("empty value not allowed for column[%d]='%.*s' - ignoring record\n", \ - pos, db_cols[pos]->len, db_cols[pos]->s); \ - continue; \ - } \ + if(!VAL_NULL(&RES_ROWS(db_res)[i].values[pos])) { \ + reg.attr.s = \ + (char*)(RES_ROWS(db_res)[i].values[pos].val.string_val); \ + reg.attr.len = strlen(reg.attr.s); \ + if(reg.attr.len == 0) { \ + LM_ERR("empty value not allowed for column[%d]='%.*s' - ignoring record\n", \ + pos, db_cols[pos]->len, db_cols[pos]->s); \ + continue; \ } \ - } while(0); + } \ +} while(0); /** * @@ -1125,7 +1125,7 @@ int uac_reg_load_db(void) if (!DB_CAPABILITY(reg_dbf, DB_CAP_ALL)) { LM_ERR("database module does not " - "implement all functions needed by the module\n"); + "implement all functions needed by the module\n"); return -1; } @@ -1162,8 +1162,8 @@ int uac_reg_load_db(void) } } else { if((ret=reg_dbf.query(reg_db_con, NULL, NULL, NULL, db_cols, - 0, 10, 0, &db_res))!=0 - || RES_ROW_N(db_res)<=0 ) + 0, 10, 0, &db_res))!=0 + || RES_ROW_N(db_res)<=0 ) { reg_dbf.free_result(reg_db_con, db_res); if( ret==0) @@ -1199,13 +1199,13 @@ int uac_reg_load_db(void) = (unsigned int)RES_ROWS(db_res)[i].values[10].val.int_val; reg.reg_delay = (unsigned int)RES_ROWS(db_res)[i].values[11].val.int_val; - + if(reg_ht_add(®)<0) { LM_ERR("Error adding reg to htable\n"); goto error; } - } + } if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) { if(reg_dbf.fetch_result(reg_db_con, &db_res, reg_fetch_rows)<0) { LM_ERR("Error while fetching!\n"); @@ -1275,7 +1275,7 @@ int uac_reg_db_refresh(str *pl_uuid) if (!DB_CAPABILITY(reg_dbf, DB_CAP_ALL)) { LM_ERR("database module does not " - "implement all functions needed by the module\n"); + "implement all functions needed by the module\n"); return -1; } @@ -1298,8 +1298,8 @@ int uac_reg_db_refresh(str *pl_uuid) db_vals[0].val.str_val.len = pl_uuid->len; if((ret=reg_dbf.query(reg_db_con, db_keys, NULL, db_vals, db_cols, - 1 /*nr keys*/, 12 /*nr cols*/, 0, &db_res))!=0 - || RES_ROW_N(db_res)<=0 ) + 1 /*nr keys*/, 12 /*nr cols*/, 0, &db_res))!=0 + || RES_ROW_N(db_res)<=0 ) { reg_dbf.free_result(reg_db_con, db_res); if( ret==0) @@ -1389,8 +1389,8 @@ int uac_reg_lookup(struct sip_msg *msg, str *src, pv_spec_t *dst, int mode) return -1; } snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s@%.*s", - reg->l_username.len, reg->l_username.s, - reg->l_domain.len, reg->l_domain.s); + reg->l_username.len, reg->l_username.s, + reg->l_domain.len, reg->l_domain.s); s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s); } else { if(parse_uri(src->s, src->len, &puri)!=0) @@ -1405,7 +1405,7 @@ int uac_reg_lookup(struct sip_msg *msg, str *src, pv_spec_t *dst, int mode) return -1; } snprintf(b_ruri, MAX_URI_SIZE, "%.*s", - reg->l_uuid.len, reg->l_uuid.s); + reg->l_uuid.len, reg->l_uuid.s); s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s); } memset(&val, 0, sizeof(pv_value_t)); @@ -1460,8 +1460,8 @@ int uac_reg_request_to(struct sip_msg *msg, str *src, unsigned int mode) // Set uri ($ru) snprintf(ruri, MAX_URI_SIZE, "sip:%.*s@%.*s", - reg->r_username.len, reg->r_username.s, - reg->r_domain.len, reg->r_domain.s); + reg->r_username.len, reg->r_username.s, + reg->r_domain.len, reg->r_domain.s); memset(&act, 0, sizeof(act)); act.type = SET_URI_T; act.val[0].type = STRING_ST; @@ -1540,23 +1540,23 @@ static void rpc_uac_reg_dump(rpc_t* rpc, void* ctx) return; } if(rpc->struct_add(th, "SSSSSSSSSdddddd", - "l_uuid", ®->r->l_uuid, - "l_username", ®->r->l_username, - "l_domain", ®->r->l_domain, - "r_username", ®->r->r_username, - "r_domain", ®->r->r_domain, - "realm", ®->r->realm, - "auth_username", ®->r->auth_username, - "auth_password", ®->r->auth_password, - "auth_proxy", (reg->r->auth_proxy.len)? - ®->r->auth_proxy:&none, - "expires", (int)reg->r->expires, - "flags", (int)reg->r->flags, - "diff_expires", (int)(reg->r->timer_expires - tn), - "timer_expires", (int)reg->r->timer_expires, - "reg_init", (int)reg->r->reg_init, - "reg_delay", (int)reg->r->reg_delay - )<0) + "l_uuid", ®->r->l_uuid, + "l_username", ®->r->l_username, + "l_domain", ®->r->l_domain, + "r_username", ®->r->r_username, + "r_domain", ®->r->r_domain, + "realm", ®->r->realm, + "auth_username", ®->r->auth_username, + "auth_password", ®->r->auth_password, + "auth_proxy", (reg->r->auth_proxy.len)? + ®->r->auth_proxy:&none, + "expires", (int)reg->r->expires, + "flags", (int)reg->r->flags, + "diff_expires", (int)(reg->r->timer_expires - tn), + "timer_expires", (int)reg->r->timer_expires, + "reg_init", (int)reg->r->reg_init, + "reg_delay", (int)reg->r->reg_delay + )<0) { lock_release(&_reg_htable->entries[i].lock); rpc->fault(ctx, 500, "Internal error adding item"); @@ -1634,21 +1634,21 @@ static void rpc_uac_reg_info(rpc_t* rpc, void* ctx) return; } if(rpc->struct_add(th, "SSSSSSSSSdddd", - "l_uuid", ®->r->l_uuid, - "l_username", ®->r->l_username, - "l_domain", ®->r->l_domain, - "r_username", ®->r->r_username, - "r_domain", ®->r->r_domain, - "realm", ®->r->realm, - "auth_username", ®->r->auth_username, - "auth_password", ®->r->auth_password, - "auth_proxy", (reg->r->auth_proxy.len)? - ®->r->auth_proxy:&none, - "expires", (int)reg->r->expires, - "flags", (int)reg->r->flags, - "diff_expires", (int)(reg->r->timer_expires - tn), - "timer_expires", (int)reg->r->timer_expires - )<0) + "l_uuid", ®->r->l_uuid, + "l_username", ®->r->l_username, + "l_domain", ®->r->l_domain, + "r_username", ®->r->r_username, + "r_domain", ®->r->r_domain, + "realm", ®->r->realm, + "auth_username", ®->r->auth_username, + "auth_password", ®->r->auth_password, + "auth_proxy", (reg->r->auth_proxy.len)? + ®->r->auth_proxy:&none, + "expires", (int)reg->r->expires, + "flags", (int)reg->r->flags, + "diff_expires", (int)(reg->r->timer_expires - tn), + "timer_expires", (int)reg->r->timer_expires + )<0) { lock_release(&_reg_htable->entries[i].lock); rpc->fault(ctx, 500, "Internal error adding item"); From 391c8ac03fc91029104b0c125e4c6e6184f1783a Mon Sep 17 00:00:00 2001 From: jaybeepee Date: Mon, 18 Jan 2016 11:52:17 +0200 Subject: [PATCH 126/142] modules/ims_auth: prevent crash if suspended transaction disappears waiting for a MAR --- modules/ims_auth/cxdx_mar.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/ims_auth/cxdx_mar.c b/modules/ims_auth/cxdx_mar.c index ff41296aa52..3dcbcb1f4c4 100644 --- a/modules/ims_auth/cxdx_mar.c +++ b/modules/ims_auth/cxdx_mar.c @@ -137,7 +137,7 @@ void async_cdp_callback(int is_timeout, void *param, AAAMessage *maa, long elaps if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { LM_ERR("t_continue: transaction not found\n"); result = CSCF_RETURN_ERROR; - goto error; + goto error1; } /* get the private_identity */ @@ -485,6 +485,8 @@ void async_cdp_callback(int is_timeout, void *param, AAAMessage *maa, long elaps tmb.unref_cell(t); } tmb.t_continue(data->tindex, data->tlabel, data->act); + +error1: free_saved_transaction_data(data); } From a86fa8f9c9d2a9f63732b43b1087e6cc5cba18fb Mon Sep 17 00:00:00 2001 From: Lucian Balaceanu Date: Tue, 19 Jan 2016 11:09:59 +0200 Subject: [PATCH 127/142] carrierroute: fixed possible kamctl fifo segfault - introduced checks to reject contiguous -{OPTION}{PARAMETER} in kamctl fifo commands e.g.: kamctl fifo cr_activate_host "-dproxy -p 49 -h proxy1" is not allowed --- modules/carrierroute/cr_fifo.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/carrierroute/cr_fifo.c b/modules/carrierroute/cr_fifo.c index 0455ba85b84..6cb6e551c11 100644 --- a/modules/carrierroute/cr_fifo.c +++ b/modules/carrierroute/cr_fifo.c @@ -490,7 +490,15 @@ static int get_fifo_opts(str * buf, fifo_opt_t * opts, unsigned int opt_set[]) { LM_DBG("token %.*s", opt_argv[i].len, opt_argv[i].s); if (opt_argv[i].len >= 1) { switch(*opt_argv[i].s) { - case '-': switch(opt_argv[i].s[1]) { + case '-': + /* -{OPTION}{PARAMETER} is not allowed */ + if (opt_argv[i].len != 2) { + FIFO_ERR(E_WRONGOPT); + LM_DBG("Unknown option: %.*s\n", opt_argv[i].len, opt_argv[i].s); + return -1; + } + + switch(opt_argv[i].s[1]) { case OPT_DOMAIN_CHR: op = OPT_DOMAIN; used_opts |= O_DOMAIN; From 311ac224b589328047fdddf7e4eb4165af501707 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 19 Jan 2016 14:27:21 +0100 Subject: [PATCH 128/142] tsilo: remove inline from free_ts_transaction() definition - the prototype is without, resulting in compile warning --- modules/tsilo/ts_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/tsilo/ts_hash.c b/modules/tsilo/ts_hash.c index 2ad2cad6112..baa2807d537 100644 --- a/modules/tsilo/ts_hash.c +++ b/modules/tsilo/ts_hash.c @@ -422,7 +422,7 @@ void remove_ts_transaction(ts_transaction_t* ts_t) * \brief Destroy a transaction and free memory * \param tma destroyed transaction */ -inline void free_ts_transaction(void *ts_t) +void free_ts_transaction(void *ts_t) { shm_free((struct ts_transaction*)ts_t); ts_t = 0; From 35c4a245b7408d595d671d4661f91900078d02db Mon Sep 17 00:00:00 2001 From: jaybeepee Date: Wed, 20 Jan 2016 09:57:44 +0200 Subject: [PATCH 129/142] modules/cdp: prevent possible deadlock when searching for sticky peers --- modules/cdp/routing.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/cdp/routing.c b/modules/cdp/routing.c index 5bd494d5c2c..51f41906be9 100644 --- a/modules/cdp/routing.c +++ b/modules/cdp/routing.c @@ -89,7 +89,9 @@ peer* get_first_connected_route(cdp_session_t* cdp_session, routing_entry *r, in /*try and find an already used peer for this session - sticky*/ if ((cdp_session->sticky_peer_fqdn.len > 0) && cdp_session->sticky_peer_fqdn.s) { //we have an old sticky peer. let's make sure it's up and connected before we use it. + AAASessionsUnlock(cdp_session->hash); /*V1.1 - Don't attempt to hold two locks at same time */ p = get_peer_by_fqdn(&cdp_session->sticky_peer_fqdn); + AAASessionsLock(cdp_session->hash); /*V1.1 - As we were...no call seems to pass cdp_session unlocked */ if (p && !p->disabled && (p->state == I_Open || p->state == R_Open) && peer_handles_application(p, app_id, vendor_id)) { p->last_selected = time(NULL); LM_DBG("Found a sticky peer [%.*s] for this session - re-using\n", p->fqdn.len, p->fqdn.s); From 49d4144480c463a94a8b56ed222c32d6075813f6 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 19 Jan 2016 20:24:28 +0100 Subject: [PATCH 130/142] uac: reset the $uac_req(...) fields when assigning $null - was done only when NULL was passed, not for values with PV_VAL_NULL --- modules/uac/uac_send.c | 168 +++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 81 deletions(-) diff --git a/modules/uac/uac_send.c b/modules/uac/uac_send.c index 11ea3f17ac6..bf4824b924c 100644 --- a/modules/uac/uac_send.c +++ b/modules/uac/uac_send.c @@ -178,13 +178,19 @@ int pv_get_uac_req(struct sip_msg *msg, pv_param_t *param, int pv_set_uac_req(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val) { + pv_value_t *tval; + if(param==NULL || tmb.t_request==NULL) return -1; + tval = val; + if((tval!=NULL) && (tval->flags&PV_VAL_NULL)) { + tval = NULL; + } switch(param->pvn.u.isname.name.n) { case 0: - if(val==NULL) + if(tval==NULL) { _uac_req.flags = 0; _uac_req.s_ruri.len = 0; @@ -202,278 +208,278 @@ int pv_set_uac_req(struct sip_msg* msg, pv_param_t *param, } break; case 1: - if(val==NULL) + if(tval==NULL) { _uac_req.s_ruri.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid value type\n"); return -1; } - if(val->rs.len>=MAX_URI_SIZE) + if(tval->rs.len>=MAX_URI_SIZE) { LM_ERR("Value size too big\n"); return -1; } - memcpy(_uac_req.s_ruri.s, val->rs.s, val->rs.len); - _uac_req.s_ruri.s[val->rs.len] = '\0'; - _uac_req.s_ruri.len = val->rs.len; + memcpy(_uac_req.s_ruri.s, tval->rs.s, tval->rs.len); + _uac_req.s_ruri.s[tval->rs.len] = '\0'; + _uac_req.s_ruri.len = tval->rs.len; break; case 2: - if(val==NULL) + if(tval==NULL) { _uac_req.s_turi.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid value type\n"); return -1; } - if(val->rs.len>=MAX_URI_SIZE) + if(tval->rs.len>=MAX_URI_SIZE) { LM_ERR("Value size too big\n"); return -1; } - memcpy(_uac_req.s_turi.s, val->rs.s, val->rs.len); - _uac_req.s_turi.s[val->rs.len] = '\0'; - _uac_req.s_turi.len = val->rs.len; + memcpy(_uac_req.s_turi.s, tval->rs.s, tval->rs.len); + _uac_req.s_turi.s[tval->rs.len] = '\0'; + _uac_req.s_turi.len = tval->rs.len; break; case 3: - if(val==NULL) + if(tval==NULL) { _uac_req.s_furi.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid value type\n"); return -1; } - if(val->rs.len>=MAX_URI_SIZE) + if(tval->rs.len>=MAX_URI_SIZE) { LM_ERR("Value size too big\n"); return -1; } - memcpy(_uac_req.s_furi.s, val->rs.s, val->rs.len); - _uac_req.s_furi.s[val->rs.len] = '\0'; - _uac_req.s_furi.len = val->rs.len; + memcpy(_uac_req.s_furi.s, tval->rs.s, tval->rs.len); + _uac_req.s_furi.s[tval->rs.len] = '\0'; + _uac_req.s_furi.len = tval->rs.len; break; case 4: - if(val==NULL) + if(tval==NULL) { _uac_req.s_hdrs.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid value type\n"); return -1; } - if(val->rs.len>=MAX_UACH_SIZE) + if(tval->rs.len>=MAX_UACH_SIZE) { LM_ERR("Value size too big\n"); return -1; } - memcpy(_uac_req.s_hdrs.s, val->rs.s, val->rs.len); - _uac_req.s_hdrs.s[val->rs.len] = '\0'; - _uac_req.s_hdrs.len = val->rs.len; + memcpy(_uac_req.s_hdrs.s, tval->rs.s, tval->rs.len); + _uac_req.s_hdrs.s[tval->rs.len] = '\0'; + _uac_req.s_hdrs.len = tval->rs.len; break; case 5: - if(val==NULL) + if(tval==NULL) { _uac_req.s_body.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid value type\n"); return -1; } - if(val->rs.len>=MAX_UACB_SIZE) + if(tval->rs.len>=MAX_UACB_SIZE) { LM_ERR("Value size too big\n"); return -1; } - memcpy(_uac_req.s_body.s, val->rs.s, val->rs.len); - _uac_req.s_body.s[val->rs.len] = '\0'; - _uac_req.s_body.len = val->rs.len; + memcpy(_uac_req.s_body.s, tval->rs.s, tval->rs.len); + _uac_req.s_body.s[tval->rs.len] = '\0'; + _uac_req.s_body.len = tval->rs.len; break; case 6: - if(val==NULL) + if(tval==NULL) { _uac_req.s_ouri.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid value type\n"); return -1; } - if(val->rs.len>=MAX_URI_SIZE) + if(tval->rs.len>=MAX_URI_SIZE) { LM_ERR("Value size too big\n"); return -1; } - memcpy(_uac_req.s_ouri.s, val->rs.s, val->rs.len); - _uac_req.s_ouri.s[val->rs.len] = '\0'; - _uac_req.s_ouri.len = val->rs.len; + memcpy(_uac_req.s_ouri.s, tval->rs.s, tval->rs.len); + _uac_req.s_ouri.s[tval->rs.len] = '\0'; + _uac_req.s_ouri.len = tval->rs.len; break; case 7: - if(val==NULL) + if(tval==NULL) { _uac_req.s_method.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid value type\n"); return -1; } - if(val->rs.len>=32) + if(tval->rs.len>=32) { LM_ERR("Value size too big\n"); return -1; } - memcpy(_uac_req.s_method.s, val->rs.s, val->rs.len); - _uac_req.s_method.s[val->rs.len] = '\0'; - _uac_req.s_method.len = val->rs.len; + memcpy(_uac_req.s_method.s, tval->rs.s, tval->rs.len); + _uac_req.s_method.s[tval->rs.len] = '\0'; + _uac_req.s_method.len = tval->rs.len; break; case 8: - if(val==NULL) + if(tval==NULL) { _uac_req.evroute = 0; return 0; } - if(!(val->flags&PV_VAL_INT)) + if(!(tval->flags&PV_VAL_INT)) { LM_ERR("Invalid value type\n"); return -1; } - _uac_req.evroute = val->ri; + _uac_req.evroute = tval->ri; break; case 9: - if(val==NULL) + if(tval==NULL) { _uac_req.s_auser.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid auth user type\n"); return -1; } - if(val->rs.len>=128) + if(tval->rs.len>=128) { LM_ERR("Value size too big\n"); return -1; } - memcpy(_uac_req.s_auser.s, val->rs.s, val->rs.len); - _uac_req.s_auser.s[val->rs.len] = '\0'; - _uac_req.s_auser.len = val->rs.len; + memcpy(_uac_req.s_auser.s, tval->rs.s, tval->rs.len); + _uac_req.s_auser.s[tval->rs.len] = '\0'; + _uac_req.s_auser.len = tval->rs.len; break; case 10: - if(val==NULL) + if(tval==NULL) { _uac_req.s_apasswd.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid auth password type\n"); return -1; } - if(val->rs.len>=64) + if(tval->rs.len>=64) { LM_ERR("Value size too big\n"); return -1; } - memcpy(_uac_req.s_apasswd.s, val->rs.s, val->rs.len); - _uac_req.s_apasswd.s[val->rs.len] = '\0'; - _uac_req.s_apasswd.len = val->rs.len; + memcpy(_uac_req.s_apasswd.s, tval->rs.s, tval->rs.len); + _uac_req.s_apasswd.s[tval->rs.len] = '\0'; + _uac_req.s_apasswd.len = tval->rs.len; break; case 11: - if(val==NULL) + if(tval==NULL) { _uac_req.s_callid.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid value type\n"); return -1; } - memcpy(_uac_req.s_callid.s, val->rs.s, val->rs.len); - _uac_req.s_callid.s[val->rs.len] = '\0'; - _uac_req.s_callid.len = val->rs.len; + memcpy(_uac_req.s_callid.s, tval->rs.s, tval->rs.len); + _uac_req.s_callid.s[tval->rs.len] = '\0'; + _uac_req.s_callid.len = tval->rs.len; break; case 12: - if(val==NULL) + if(tval==NULL) { _uac_req.s_apasswd.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid socket pv type\n"); return -1; } - if(val->rs.len>=MAX_URI_SIZE) + if(tval->rs.len>=MAX_URI_SIZE) { LM_ERR("Value size too big\n"); return -1; } - memcpy(_uac_req.s_sock.s, val->rs.s, val->rs.len); - _uac_req.s_sock.s[val->rs.len] = '\0'; - _uac_req.s_sock.len = val->rs.len; + memcpy(_uac_req.s_sock.s, tval->rs.s, tval->rs.len); + _uac_req.s_sock.s[tval->rs.len] = '\0'; + _uac_req.s_sock.len = tval->rs.len; break; case 14: - if(val==NULL) + if(tval==NULL) { _uac_req.s_evparam.len = 0; return 0; } - if(!(val->flags&PV_VAL_STR)) + if(!(tval->flags&PV_VAL_STR)) { LM_ERR("Invalid value type\n"); return -1; } - if(val->rs.len>=MAX_UACD_SIZE) + if(tval->rs.len>=MAX_UACD_SIZE) { LM_ERR("Value size too big\n"); return -1; } - memcpy(_uac_req.s_evparam.s, val->rs.s, val->rs.len); - _uac_req.s_evparam.s[val->rs.len] = '\0'; - _uac_req.s_evparam.len = val->rs.len; + memcpy(_uac_req.s_evparam.s, tval->rs.s, tval->rs.len); + _uac_req.s_evparam.s[tval->rs.len] = '\0'; + _uac_req.s_evparam.len = tval->rs.len; break; case 15: - if(val==NULL) + if(tval==NULL) { _uac_req.evcode = 0; return 0; } - if(!(val->flags&PV_VAL_INT)) + if(!(tval->flags&PV_VAL_INT)) { LM_ERR("Invalid value type\n"); return -1; } - _uac_req.evcode = val->ri; + _uac_req.evcode = tval->ri; break; case 16: - if(val==NULL) + if(tval==NULL) { _uac_req.evtype = 0; return 0; } - if(!(val->flags&PV_VAL_INT)) + if(!(tval->flags&PV_VAL_INT)) { LM_ERR("Invalid value type\n"); return -1; } - _uac_req.evtype = val->ri; + _uac_req.evtype = tval->ri; break; } return 0; From 368f9ccdfefb9f9261c1b32f271c1d5838cb8fff Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 19 Jan 2016 20:27:32 +0100 Subject: [PATCH 131/142] uac: notes about the flags of remote registration profiles --- modules/uac/uac_reg.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/uac/uac_reg.c b/modules/uac/uac_reg.c index c0cf6e8def4..8ff63bdef28 100644 --- a/modules/uac/uac_reg.c +++ b/modules/uac/uac_reg.c @@ -42,11 +42,11 @@ #include "auth_hdr.h" #include "uac_reg.h" -#define UAC_REG_DISABLED (1<<0) -#define UAC_REG_ONGOING (1<<1) -#define UAC_REG_ONLINE (1<<2) -#define UAC_REG_AUTHSENT (1<<3) -#define UAC_REG_INIT (1<<4) +#define UAC_REG_DISABLED (1<<0) /* registration disabled */ +#define UAC_REG_ONGOING (1<<1) /* registration on progress */ +#define UAC_REG_ONLINE (1<<2) /* registered */ +#define UAC_REG_AUTHSENT (1<<3) /* registration with auth in progress */ +#define UAC_REG_INIT (1<<4) /* registration initialized */ #define MAX_UACH_SIZE 2048 #define UAC_REG_GC_INTERVAL 150 From f1cf7f99caca99c379f4785ebb449e7b1b5d30aa Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 19 Jan 2016 20:36:43 +0100 Subject: [PATCH 132/142] uac: documentation of flags returned via rpc command --- modules/uac/doc/uac_admin.xml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/modules/uac/doc/uac_admin.xml b/modules/uac/doc/uac_admin.xml index 3e6021fe1b7..dc95ec8fadc 100644 --- a/modules/uac/doc/uac_admin.xml +++ b/modules/uac/doc/uac_admin.xml @@ -899,6 +899,27 @@ event_route[uac:reply] { The value is what should be matcheg against the value of the attribute in the remote registration record. + + The state of the registration is reflected in the flags field: + + + 1 (2^0) - registration profile is disabled + + + 2 (2^1) - registration in progress + + + 4 (2^2) - registration succeeded + + + 8 (2^3) - registration in progres with authentication + + + 16 (2^4) - registration initialized (after loading from database, + the registration process was initialized) + + + <function>uac.reg_info</function> usage From 475a2444c36a8255c5c7ca068721566346919b4a Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 19 Jan 2016 20:36:58 +0100 Subject: [PATCH 133/142] uac: refresh content of readme --- modules/uac/README | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/uac/README b/modules/uac/README index 4e8b3241cb5..b60a33b6f48 100644 --- a/modules/uac/README +++ b/modules/uac/README @@ -785,6 +785,14 @@ event_route[uac:reply] { should be matcheg against the value of the attribute in the remote registration record. + The state of the registration is reflected in the flags field: + * 1 (2^0) - registration profile is disabled + * 2 (2^1) - registration in progress + * 4 (2^2) - registration succeeded + * 8 (2^3) - registration in progres with authentication + * 16 (2^4) - registration initialized (after loading from database, + the registration process was initialized) + Example 1.29. uac.reg_info usage ... kamcmd uac.reg_info l_uuid account123 From c084e0b389cb63134f2752053e30529f2605c39b Mon Sep 17 00:00:00 2001 From: jaybeepee Date: Wed, 20 Jan 2016 10:31:38 +0200 Subject: [PATCH 134/142] modules/ims_charging: fixed charging stats --- modules/ims_charging/dialog.c | 2 ++ modules/ims_charging/ims_ro.c | 10 ++++++++-- modules/ims_charging/mod.c | 3 +++ modules/ims_charging/ro_session_hash.h | 7 ++++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/modules/ims_charging/dialog.c b/modules/ims_charging/dialog.c index b9f77fe53d2..9e463cd46c8 100644 --- a/modules/ims_charging/dialog.c +++ b/modules/ims_charging/dialog.c @@ -4,6 +4,7 @@ #include "../ims_usrloc_scscf/usrloc.h" #include "../ims_usrloc_scscf/udomain.h" #include "ro_db_handler.h" +#include "ims_charging_stats.h" struct cdp_binds cdpb; @@ -11,6 +12,7 @@ extern usrloc_api_t ul; extern int ro_db_mode; extern char *domain; extern struct dlg_binds dlgb; +extern struct ims_charging_counters_h ims_charging_cnts_h; void dlg_callback_received(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) { LM_DBG("Received dialog callback event [%d]\n", type); diff --git a/modules/ims_charging/ims_ro.c b/modules/ims_charging/ims_ro.c index 3dafc2bc9b5..783a929c456 100644 --- a/modules/ims_charging/ims_ro.c +++ b/modules/ims_charging/ims_ro.c @@ -721,6 +721,7 @@ static void resume_on_interim_ccr(int is_timeout, void *param, AAAMessage *cca, goto success; error: + counter_inc(ims_charging_cnts_h.failed_interim_ccr); if (ro_cca_data) Ro_free_CCA(ro_cca_data); @@ -904,7 +905,7 @@ void send_ccr_stop(struct ro_session *ro_session) { Ro_free_CCR(ro_ccr_data); counter_inc(ims_charging_cnts_h.final_ccrs); - counter_add(ims_charging_cnts_h.active_ro_sessions, -1); +// counter_add(ims_charging_cnts_h.active_ro_sessions, -1); return; error1: @@ -935,6 +936,7 @@ static void resume_on_termination_ccr(int is_timeout, void *param, AAAMessage *c if (!cca) { LM_ERR("Error in termination CCR.\n"); + counter_inc(ims_charging_cnts_h.failed_final_ccrs); return; } @@ -942,6 +944,7 @@ static void resume_on_termination_ccr(int is_timeout, void *param, AAAMessage *c if (ro_cca_data == NULL) { LM_DBG("Could not parse CCA message response.\n"); + counter_inc(ims_charging_cnts_h.failed_final_ccrs); return; } @@ -955,6 +958,7 @@ static void resume_on_termination_ccr(int is_timeout, void *param, AAAMessage *c counter_inc(ims_charging_cnts_h.successful_final_ccrs); error: + counter_inc(ims_charging_cnts_h.failed_final_ccrs); Ro_free_CCA(ro_cca_data); if (!is_timeout && cca) { cdpb.AAAFreeMessage(&cca); @@ -1184,6 +1188,7 @@ int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, int reservat } counter_inc(ims_charging_cnts_h.initial_ccrs); + counter_inc(ims_charging_cnts_h.active_ro_sessions); if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri return RO_RETURN_BREAK; @@ -1305,7 +1310,6 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca, shm_free(ssd); counter_inc(ims_charging_cnts_h.successful_initial_ccrs); - counter_inc(ims_charging_cnts_h.active_ro_sessions); return; @@ -1314,6 +1318,8 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca, error0: LM_DBG("Trying to reserve credit on initial INVITE failed on cdp callback\n"); +// counter_add(ims_charging_cnts_h.active_ro_sessions, -1); /*we bumped active on the original initial ccr sent */ + counter_inc(ims_charging_cnts_h.failed_initial_ccrs); /* drop by one as theoretically this is failed initial ccr */ create_cca_return_code(error_code); if (!is_timeout && cca) { diff --git a/modules/ims_charging/mod.c b/modules/ims_charging/mod.c index e769a522958..9f7774e5fc2 100644 --- a/modules/ims_charging/mod.c +++ b/modules/ims_charging/mod.c @@ -21,6 +21,8 @@ #include "../../lib/ims/ims_getters.h" #include "ro_db_handler.h" #include "ims_charging_stats.h" +#include "ro_session_hash.h" +#include "ims_charging_stats.h" MODULE_VERSION @@ -57,6 +59,7 @@ client_ro_cfg cfg = { str_init("scscf.ims.smilecoms.com"), 0 }; +extern struct ims_charging_counters_h ims_charging_cnts_h; struct cdp_binds cdpb; struct dlg_binds dlgb; cdp_avp_bind_t *cdp_avp; diff --git a/modules/ims_charging/ro_session_hash.h b/modules/ims_charging/ro_session_hash.h index 8fa622f3f7e..07d373e39d1 100644 --- a/modules/ims_charging/ro_session_hash.h +++ b/modules/ims_charging/ro_session_hash.h @@ -11,6 +11,7 @@ #include "ro_timer.h" #include "../../mem/shm_mem.h" #include "../ims_usrloc_scscf/usrloc.h" +#include "ims_charging_stats.h" #include @@ -22,6 +23,8 @@ #define MAX_PANI_LEN 100 +extern struct ims_charging_counters_h ims_charging_cnts_h; + enum ro_session_event_type { pending, answered, @@ -72,7 +75,7 @@ struct ro_session { int rating_group; int service_identifier; unsigned int is_final_allocation; - unsigned int billed; + long billed; }; /*! entries in the main ro_session table */ @@ -163,6 +166,8 @@ static inline void unlink_unsafe_ro_session(struct ro_session_entry *ro_session_ ro_session_entry->first = ro_session->next; ro_session->next = ro_session->prev = 0; + + counter_add(ims_charging_cnts_h.active_ro_sessions, -1); return; } From e010736858bb04766b5871fc6ede0b1279d84132 Mon Sep 17 00:00:00 2001 From: jaybeepee Date: Wed, 20 Jan 2016 10:36:53 +0200 Subject: [PATCH 135/142] modules/ims_charging: added ability to send vendor-specific charge information - this allows for call dispositions to be stored and reported on in OCS - by default this id disabled (modparam - vendor_specific_chargeinfo=0) --- modules/ims_charging/dialog.c | 45 +++++++++--- modules/ims_charging/dialog.h | 2 +- modules/ims_charging/ims_ro.c | 38 +++++++++- modules/ims_charging/ims_ro.h | 7 +- modules/ims_charging/mod.c | 99 +++++++++++++++++++++++++- modules/ims_charging/ro_session_hash.c | 2 +- modules/ims_charging/ro_session_hash.h | 1 + 7 files changed, 178 insertions(+), 16 deletions(-) diff --git a/modules/ims_charging/dialog.c b/modules/ims_charging/dialog.c index 9e463cd46c8..e14793849fc 100644 --- a/modules/ims_charging/dialog.c +++ b/modules/ims_charging/dialog.c @@ -16,14 +16,19 @@ extern struct ims_charging_counters_h ims_charging_cnts_h; void dlg_callback_received(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) { LM_DBG("Received dialog callback event [%d]\n", type); + unsigned int termcode = 0; switch (type) { case DLGCB_CONFIRMED: dlg_answered(dlg, type, _params); break; case DLGCB_TERMINATED: + dlg_terminated(dlg, type, termcode, "normal call clearing", _params); + break; case DLGCB_FAILED: + dlg_terminated(dlg, type, termcode, "call failed", _params); + break; case DLGCB_EXPIRED: - dlg_terminated(dlg, type, _params); + dlg_terminated(dlg, type, termcode, "dialog timeout", _params); break; default: LM_WARN("Received unknown dialog callback [%d]\n", type); @@ -31,7 +36,6 @@ void dlg_callback_received(struct dlg_cell *dlg, int type, struct dlg_cb_params } void dlg_answered(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) { - struct sip_msg *reply; struct ro_session* session = 0; struct ro_session_entry* ro_session_entry; time_t now = get_current_time_micro(); @@ -116,19 +120,38 @@ void dlg_answered(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) } -void dlg_terminated(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) { +void dlg_terminated(struct dlg_cell *dlg, int type, unsigned int termcode, char* reason, struct dlg_cb_params *_params) { //int i; int unref = 0; struct ro_session *ro_session = 0; struct ro_session_entry *ro_session_entry; struct sip_msg *request; + str s_reason; + + s_reason.s = reason; + s_reason.len = strlen(reason); - LM_DBG("dialog [%p] terminated, lets send stop record\n", dlg); + LM_DBG("dialog [%p] terminated on type [%d], lets send stop record\n", dlg, type); if (!_params) { return; } + LM_DBG("Direction is %d\n", _params->direction); + if (_params->req) { + if (_params->req->first_line.u.request.method_value == METHOD_BYE) { + if (_params->direction == DLG_DIR_DOWNSTREAM) { + LM_DBG("Dialog ended by Caller\n"); + } else { + LM_DBG("Dialog ended by Callee\n"); + } + } else { + LM_DBG("Request is %.*s\n", _params->req->first_line.u.request.method.len, _params->req->first_line.u.request.method.s); + } + } else if (_params->rpl) { + LM_DBG("Reply is [%d - %.*s]", _params->rpl->first_line.u.reply.statuscode, _params->rpl->first_line.u.reply.reason.len, _params->rpl->first_line.u.reply.reason.s); + } + ro_session = (struct ro_session*)*_params->param; if (!ro_session) { LM_ERR("Ro Session object is NULL...... aborting\n"); @@ -155,14 +178,14 @@ void dlg_terminated(struct dlg_cell *dlg, int type, struct dlg_cb_params *_param //double processing for various dialog_terminated callback events. //If however, the call was never answered, then we can continue as normal ro_session_lock(ro_session_table, ro_session_entry); - if (!ro_session->active && (ro_session->start_time != 0)) { - unref_ro_session(ro_session,1); - LM_ERR("Ro Session is not active, but may have been answered [%d]\n", (int)ro_session->start_time); + + LM_DBG("processing dlg_terminated in Ro and session [%.*s] has active = %d", ro_session->ro_session_id.len, ro_session->ro_session_id.s, ro_session->active); + if ((!ro_session->active && (ro_session->start_time != 0)) || (ro_session->ccr_sent == 1)) { + unref_ro_session_unsafe(ro_session,1,ro_session_entry); + LM_ERR("CCR already sent or Ro Session is not active, but may have been answered [%d]\n", (int)ro_session->start_time); ro_session_unlock(ro_session_table, ro_session_entry); return; } - - if (ro_session->active) { // if the call was never activated, there's no timer to remove int ret = remove_ro_timer(&ro_session->ro_tl); @@ -178,8 +201,10 @@ void dlg_terminated(struct dlg_cell *dlg, int type, struct dlg_cb_params *_param } LM_DBG("Sending CCR STOP on Ro_Session [%p]\n", ro_session); - send_ccr_stop(ro_session); + send_ccr_stop_with_param(ro_session, termcode, &s_reason); ro_session->active = -1; //deleted.... terminated .... + ro_session->ccr_sent = 1; +// counter_add(ims_charging_cnts_h.active_ro_sessions, -1); if (ro_db_mode == DB_MODE_REALTIME) { ro_session->flags |= RO_SESSION_FLAG_DELETED; diff --git a/modules/ims_charging/dialog.h b/modules/ims_charging/dialog.h index e64b4d99e37..a295ad31469 100644 --- a/modules/ims_charging/dialog.h +++ b/modules/ims_charging/dialog.h @@ -9,7 +9,7 @@ extern int ro_timer_buffer; void dlg_callback_received(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params); -void dlg_terminated(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params); +void dlg_terminated(struct dlg_cell *dlg, int type, unsigned int termcode, char* reason, struct dlg_cb_params *_params); void dlg_answered(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params); void add_dlg_data_to_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params); void remove_dlg_data_from_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params); diff --git a/modules/ims_charging/ims_ro.c b/modules/ims_charging/ims_ro.c index 783a929c456..73be3609ef3 100644 --- a/modules/ims_charging/ims_ro.c +++ b/modules/ims_charging/ims_ro.c @@ -42,6 +42,8 @@ extern cdp_avp_bind_t *cdp_avp; extern str ro_forced_peer; extern int ro_db_mode; extern struct ims_charging_counters_h ims_charging_cnts_h; +extern int vendor_specific_id; +extern int vendor_specific_chargeinfo; struct session_setup_data { struct ro_session *ro_session; @@ -180,6 +182,21 @@ inline int Ro_add_termination_cause(AAAMessage *msg, unsigned int term_code) { return Ro_add_avp(msg, s.s, s.len, AVP_Termination_Cause, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__); } +inline int Ro_add_vendor_specific_termination_cause(AAAMessage *msg, unsigned int term_code) { + char x[4]; + str s = {x, 4}; + uint32_t code = htonl(term_code); + memcpy(x, &code, sizeof (uint32_t)); + + return Ro_add_avp(msg, s.s, s.len, VS_TERMCODE, AAA_AVP_FLAG_VENDOR_SPECIFIC, 10, AVP_DUPLICATE_DATA, __FUNCTION__); +} + +inline int Ro_add_vendor_specific_termination_reason(AAAMessage *msg, str* reason) { + return Ro_add_avp(msg, reason->s, reason->len, VS_TERMREASON, AAA_AVP_FLAG_VENDOR_SPECIFIC, 10, AVP_DUPLICATE_DATA, __FUNCTION__); +} + + + /* called only when building stop record AVPS */ inline int Ro_add_multiple_service_credit_Control_stop(AAAMessage *msg, int used_unit, int active_rating_group, int active_service_identifier) { char x[4]; @@ -745,7 +762,7 @@ long get_current_time_micro() { return tv.tv_sec*1000000 + tv.tv_usec; } -void send_ccr_stop(struct ro_session *ro_session) { +void send_ccr_stop_with_param(struct ro_session *ro_session, unsigned int code, str* reason) { AAASession * auth = 0; Ro_CCR_t * ro_ccr_data = 0; AAAMessage * ccr = 0; @@ -890,6 +907,16 @@ void send_ccr_stop(struct ro_session *ro_session) { LM_ERR("problem add Termination cause AVP to STOP record.\n"); } + if (vendor_specific_chargeinfo) { + if (!Ro_add_vendor_specific_termination_cause(ccr, code)) { + LM_ERR("problem add Termination cause AVP to STOP record.\n"); + } + + if (!Ro_add_vendor_specific_termination_reason(ccr, reason)) { + LM_ERR("problem add Termination cause AVP to STOP record.\n"); + } + } + cdpb.AAASessionsUnlock(auth->hash); if (ro_forced_peer.len > 0) { @@ -956,6 +983,11 @@ static void resume_on_termination_ccr(int is_timeout, void *param, AAAMessage *c } counter_inc(ims_charging_cnts_h.successful_final_ccrs); + Ro_free_CCA(ro_cca_data); + if (!is_timeout && cca) { + cdpb.AAAFreeMessage(&cca); + } + return; error: counter_inc(ims_charging_cnts_h.failed_final_ccrs); @@ -1162,6 +1194,7 @@ int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, int reservat LM_DBG("new CC Ro Session ID: [%.*s] stored in shared memory address [%p]\n", cc_acc_session->id.len, cc_acc_session->id.s, new_session); LM_DBG("Sending CCR Diameter message.\n"); +// new_session->ccr_sent = 1; //assume we will send successfully cdpb.AAASessionsUnlock(cc_acc_session->hash); if (ro_forced_peer.len > 0) { @@ -1174,6 +1207,7 @@ int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, int reservat if (ret != 1) { LM_ERR("Failed to send Diameter CCR\n"); +// new_session->ccr_sent = 0; goto error; } @@ -1290,7 +1324,7 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca, LM_DBG("Freeing CCA message\n"); cdpb.AAAFreeMessage(&cca); - link_ro_session(ssd->ro_session, 1); /* create extra ref for the fact that dialog has a handle in the callbacks */ + link_ro_session(ssd->ro_session, 0); if (ro_db_mode == DB_MODE_REALTIME) { ssd->ro_session->flags |= RO_SESSION_FLAG_NEW; diff --git a/modules/ims_charging/ims_ro.h b/modules/ims_charging/ims_ro.h index 361bd8f57ae..7a1fc3a7bb7 100644 --- a/modules/ims_charging/ims_ro.h +++ b/modules/ims_charging/ims_ro.h @@ -6,6 +6,11 @@ #include "../dialog_ng/dlg_hash.h" #include "ro_session_hash.h" +typedef enum { + VS_TERMCODE = 3, + VS_TERMREASON = 2 +} vs_term_avp; + struct interim_ccr { struct ro_session* ro_session; int new_credit; @@ -19,7 +24,7 @@ int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, int reservat str *incoming_trunk_id, str *outgoing_trunk_id, str *enb_cell_id, cfg_action_t* action, unsigned int tindex, unsigned int tlabel); long get_current_time_micro(); void send_ccr_interim(struct ro_session* ro_session, unsigned int used, unsigned int reserve); -void send_ccr_stop(struct ro_session *ro_session); +void send_ccr_stop_with_param(struct ro_session *ro_session, unsigned int code, str* reason); int get_direction_as_int(str* direction); #endif /* CLIENT_RF_IMS_RO_H */ diff --git a/modules/ims_charging/mod.c b/modules/ims_charging/mod.c index 9f7774e5fc2..c01cb8df536 100644 --- a/modules/ims_charging/mod.c +++ b/modules/ims_charging/mod.c @@ -33,6 +33,9 @@ char* ro_service_context_id_ext_s = "ext"; char* ro_service_context_id_mnc_s = "01"; char* ro_service_context_id_mcc_s = "001"; char* ro_service_context_id_release_s = "8"; +int termination_code = 0; +int vendor_specific_id = 10; +int vendor_specific_chargeinfo = 0; static int ro_session_hash_size = 4096; int ro_timer_buffer = 5; int interim_request_credits = 30; @@ -84,6 +87,7 @@ static int mod_child_init(int); static void mod_destroy(void); static int w_ro_ccr(struct sip_msg *msg, char* route_name, char* direction, int reservation_units, char* incoming_trunk_id, char* outgoing_trunk_id); +static int w_ro_ccr_stop(struct sip_msg *msg, char* direction, char* _code, char* _reason); //void ro_session_ontimeout(struct ro_tl *tl); @@ -91,10 +95,12 @@ int create_response_avp_string(char* name, str* val); static int w_ro_set_session_id_avp(struct sip_msg *msg, char *str1, char *str2); static int ro_fixup(void **param, int param_no); +static int ro_fixup_stop(void **param, int param_no); static cmd_export_t cmds[] = { { "Ro_CCR", (cmd_function) w_ro_ccr, 5, ro_fixup, 0, REQUEST_ROUTE }, - { "Ro_set_session_id_avp", (cmd_function) w_ro_set_session_id_avp, 0, 0, 0, REQUEST_ROUTE | ONREPLY_ROUTE }, + { "Ro_CCR_Stop",(cmd_function) w_ro_ccr_stop, 3, ro_fixup_stop, 0, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE}, + { "Ro_set_session_id_avp", (cmd_function) w_ro_set_session_id_avp, 0, 0, 0, REQUEST_ROUTE | ONREPLY_ROUTE }, { 0, 0, 0, 0, 0, 0 } }; @@ -127,6 +133,8 @@ static param_export_t params[] = { { "db_mode", INT_PARAM, &ro_db_mode_param }, { "db_url", PARAM_STRING, &db_url }, { "db_update_period", INT_PARAM, &db_update_period }, + { "vendor_specific_chargeinfo", INT_PARAM, &vendor_specific_chargeinfo }, /* VSI for extra charing info in Ro */ + { "vendor_specific_id", INT_PARAM, &vendor_specific_id }, /* VSI for extra charing info in Ro */ { 0, 0, 0 } }; @@ -355,11 +363,93 @@ static int w_ro_set_session_id_avp(struct sip_msg *msg, char *str1, char *str2) //set avp response with session id res = create_response_avp_string("ro_session_id", &ro_session->ro_session_id); dlgb.release_dlg(dlg); + unref_ro_session(ro_session, 1); return res; } +static int w_ro_ccr_stop(struct sip_msg *msg, char* c_direction, char* _code, char* _reason) { + struct ro_session* ro_session; + struct ro_session_entry *ro_session_entry; + unsigned int h_entry; + str s_code, s_reason; + unsigned int code; + int dir = 0; /*any side*/ + + LM_DBG("Inside Ro_CCR_Stop with direction [%s]\n", c_direction); + if (strlen(c_direction) == 4) { + if (c_direction[0] == 'O' || c_direction[0] == 'o') { + dir = RO_ORIG_DIRECTION; + } else { + dir = RO_TERM_DIRECTION; + } + } else { + LM_ERR("Unknown direction [%s] to terminate\n", c_direction); + return RO_RETURN_FALSE; + } + struct dlg_cell* dlg = dlgb.get_dlg(msg); + if (!dlg) { + LM_ERR("Unable to find dialog to send CCR STOP record\n"); + return RO_RETURN_ERROR; + } + if (get_str_fparam(&s_code, msg, (fparam_t*) _code) < 0) { + LM_ERR("failed to get code\n"); + return RO_RETURN_ERROR; + } + LM_DBG("Code is [%.*s]\n", s_code.len, s_code.s); + if (get_str_fparam(&s_reason, msg, (fparam_t*) _reason) < 0) { + LM_ERR("failed to get reason\n"); + return RO_RETURN_ERROR; + } + if (str2int(&s_code, &code) != 0) { + LM_ERR("Bad response code: [%.*s]\n", s_code.len, s_code.s); + return RO_RETURN_FALSE; + } + +// switch (code) { +// case 486: +// termcode = VS_TERMCODE_BUSYHERE; +// break; +// case 487: +// termcode = VS_TERMCODE_CANCELLED; +// break; +// case 480: +// case 408: +// /* subscriber not available */ +// termcode = VS_TERMCODE_NOTFOUND; +// break; +// } + + LM_DBG("Sending Stop record with code [%d] and reason [%.*s]\n", code, s_reason.len, s_reason.s); + + LM_DBG("Found DLG [%d : %d]\n", dlg->h_id, dlg->h_entry); + + ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, dir, 0); + if (ro_session == NULL) { + LM_DBG("no ro_session - ignoring\n"); + return RO_RETURN_TRUE; + } + h_entry = ro_session->h_entry; + ro_session_entry = &(ro_session_table->entries[h_entry]); + + ro_session_lock(ro_session_table, ro_session_entry); + + if (ro_session->ccr_sent == 1) { + LM_DBG("Ro CCR already sent for session [%.*s]\n", ro_session->ro_session_id.len, ro_session->ro_session_id.s); + goto done; + } + send_ccr_stop_with_param(ro_session, code, &s_reason); + //TODO = check the CCR was sent successfully. + LM_DBG("Setting Ro session [%.*s] ccr_sent to 1\n", ro_session->ro_session_id.len, ro_session->ro_session_id.s); + ro_session->ccr_sent = 1; + ro_session->active = -1; +// counter_add(ims_charging_cnts_h.active_ro_sessions, -1); +done: + unref_ro_session_unsafe(ro_session, 1, ro_session_entry); + ro_session_unlock(ro_session_table, ro_session_entry); + return RO_RETURN_TRUE; +} static int w_ro_ccr(struct sip_msg *msg, char* c_route_name, char* c_direction, int reservation_units, char* c_incoming_trunk_id, char* c_outgoing_trunk_id) { /* PSEUDOCODE/NOTES @@ -544,3 +634,10 @@ static int ro_fixup(void **param, int param_no) { return 0; } + +static int ro_fixup_stop(void **param, int param_no) { + if (param_no == 2 || param_no == 3) { + return fixup_var_pve_12(param, param_no); + } + return 0; +} diff --git a/modules/ims_charging/ro_session_hash.c b/modules/ims_charging/ro_session_hash.c index 9c2866cf8ef..850d99f5e27 100644 --- a/modules/ims_charging/ro_session_hash.c +++ b/modules/ims_charging/ro_session_hash.c @@ -227,7 +227,7 @@ struct ro_session* build_new_ro_session(int direction, int auth_appid, int auth_ new_ro_session->h_entry = dlg_h_entry; /* we will use the same entry ID as the dlg - saves us using our own hash function */ new_ro_session->h_id = 0; - new_ro_session->ref = 0; + new_ro_session->ref = 1; new_ro_session->rating_group = active_rating_group; new_ro_session->service_identifier = active_service_identifier; diff --git a/modules/ims_charging/ro_session_hash.h b/modules/ims_charging/ro_session_hash.h index 07d373e39d1..422e502e23b 100644 --- a/modules/ims_charging/ro_session_hash.h +++ b/modules/ims_charging/ro_session_hash.h @@ -76,6 +76,7 @@ struct ro_session { int service_identifier; unsigned int is_final_allocation; long billed; + unsigned int ccr_sent; }; /*! entries in the main ro_session table */ From 8effb18ca9ce7b1da257fc804d7bef0ec79297f3 Mon Sep 17 00:00:00 2001 From: jaybeepee Date: Wed, 20 Jan 2016 10:50:04 +0200 Subject: [PATCH 136/142] modules/ims_charging: removed unused code linking to ims_usrloc_scscf --- modules/ims_charging/dialog.c | 89 -------------------------- modules/ims_charging/dialog.h | 2 - modules/ims_charging/mod.c | 23 ------- modules/ims_charging/ro_session_hash.h | 1 - 4 files changed, 115 deletions(-) diff --git a/modules/ims_charging/dialog.c b/modules/ims_charging/dialog.c index e14793849fc..3ee608babe0 100644 --- a/modules/ims_charging/dialog.c +++ b/modules/ims_charging/dialog.c @@ -1,14 +1,11 @@ #include "mod.h" #include "dialog.h" #include "ro_session_hash.h" -#include "../ims_usrloc_scscf/usrloc.h" -#include "../ims_usrloc_scscf/udomain.h" #include "ro_db_handler.h" #include "ims_charging_stats.h" struct cdp_binds cdpb; -extern usrloc_api_t ul; extern int ro_db_mode; extern char *domain; extern struct dlg_binds dlgb; @@ -221,89 +218,3 @@ void dlg_terminated(struct dlg_cell *dlg, int type, unsigned int termcode, char* //} } } - -void remove_dlg_data_from_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) { - - struct impu_data *impu_data; - impurecord_t* implicit_impurecord = 0; - struct ucontact* ucontact; - str callid = {0, 0}; - str path = {0, 0}; - udomain_t* domain_t; - - LM_DBG("dialog [%p] terminated, lets remove dlg data from contact\n", dlg); - - if (ul.register_udomain(domain, &domain_t) < 0) { - LM_ERR("Unable to register usrloc domain....aborting\n"); - return; - } - - if(_params && _params->param){ - impu_data = (struct impu_data*)*_params->param; - if (!impu_data) { - LM_ERR("IMPU data object is NULL...... aborting\n"); - return; - } - - LM_DBG("IMPU data is present, contact: <%.*s> identity <%.*s>", impu_data->contact.len, impu_data->contact.s, impu_data->identity.len, impu_data->identity.s); - LM_DBG("IMPU data domain <%.*s>", domain_t->name->len, domain_t->name->s); - - ul.lock_udomain(domain_t, &impu_data->identity); - if (ul.get_impurecord(domain_t, &impu_data->identity, &implicit_impurecord) != 0) { - LM_DBG("usrloc does not have imprecord for implicity IMPU, ignore\n"); - }else { - if (ul.get_ucontact(&impu_data->contact, &callid, &path, 0/*cseq*/, &ucontact) != 0) { //contact does not exist - LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_PORT_IP_ONLY\n", impu_data->contact.len, impu_data->contact.s); - } else {//contact exists so add dialog data to it - ul.remove_dialog_data_from_contact(ucontact, dlg->h_entry, dlg->h_id); - ul.release_ucontact(ucontact); - } - } - ul.unlock_udomain(domain_t, &impu_data->identity); - free_impu_data(impu_data); - } - - //we referenced the dialog when we registered for callbacks on it... - dlgb.release_dlg(dlg); -} - -void add_dlg_data_to_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) { - - struct impu_data *impu_data; - impurecord_t* implicit_impurecord = 0; - struct ucontact* ucontact; - str callid = {0, 0}; - str path = {0, 0}; - udomain_t* domain_t; - - LM_DBG("dialog [%p] confirmed, lets add dlg data to contact\n", dlg); - - if (ul.register_udomain(domain, &domain_t) < 0) { - LM_ERR("Unable to register usrloc domain....aborting\n"); - return; - } - - if(_params && _params->param){ - impu_data = (struct impu_data*)*_params->param; - if (!impu_data) { - LM_ERR("IMPU data object is NULL...... aborting\n"); - return; - } - - LM_DBG("IMPU data is present, contact: <%.*s> identity <%.*s>", impu_data->contact.len, impu_data->contact.s, impu_data->identity.len, impu_data->identity.s); - LM_DBG("IMPU data domain <%.*s>", domain_t->name->len, domain_t->name->s); - - ul.lock_udomain(domain_t, &impu_data->identity); - if (ul.get_impurecord(domain_t, &impu_data->identity, &implicit_impurecord) != 0) { - LM_DBG("usrloc does not have imprecord for implicity IMPU, ignore\n"); - }else { - if (ul.get_ucontact(&impu_data->contact, &callid, &path, 0/*cseq*/, &ucontact) != 0) { //contact does not exist - LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_PORT_IP_ONLY\n", impu_data->contact.len, impu_data->contact.s); - } else {//contact exists so add dialog data to it - ul.add_dialog_data_to_contact(ucontact, dlg->h_entry, dlg->h_id); - ul.release_ucontact(ucontact); - } - } - ul.unlock_udomain(domain_t, &impu_data->identity); - } -} diff --git a/modules/ims_charging/dialog.h b/modules/ims_charging/dialog.h index a295ad31469..410002d13b5 100644 --- a/modules/ims_charging/dialog.h +++ b/modules/ims_charging/dialog.h @@ -11,7 +11,5 @@ extern int ro_timer_buffer; void dlg_callback_received(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params); void dlg_terminated(struct dlg_cell *dlg, int type, unsigned int termcode, char* reason, struct dlg_cb_params *_params); void dlg_answered(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params); -void add_dlg_data_to_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params); -void remove_dlg_data_from_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params); #endif diff --git a/modules/ims_charging/mod.c b/modules/ims_charging/mod.c index c01cb8df536..c4a797dcf4a 100644 --- a/modules/ims_charging/mod.c +++ b/modules/ims_charging/mod.c @@ -17,7 +17,6 @@ #include "ims_ro.h" #include "config.h" #include "dialog.h" -#include "../ims_usrloc_scscf/usrloc.h" #include "../../lib/ims/ims_getters.h" #include "ro_db_handler.h" #include "ims_charging_stats.h" @@ -68,8 +67,6 @@ struct dlg_binds dlgb; cdp_avp_bind_t *cdp_avp; struct tm_binds tmb; -usrloc_api_t ul; /*!< Structure containing pointers to usrloc functions*/ - char* rx_dest_realm_s = "ims.smilecoms.com"; str rx_dest_realm; /* Only used if we want to force the Ro peer usually this is configured at a stack level and the first request uses realm routing */ @@ -184,7 +181,6 @@ int fix_parameters() { static int mod_init(void) { int n; load_tm_f load_tm; - bind_usrloc_t bind_usrloc; if (!fix_parameters()) { LM_ERR("unable to set Ro configuration parameters correctly\n"); @@ -215,16 +211,6 @@ static int mod_init(void) { goto error; } - bind_usrloc = (bind_usrloc_t) find_export("ul_bind_usrloc", 1, 0); - if (!bind_usrloc) { - LM_ERR("can't bind usrloc\n"); - return -1; - } - - if (bind_usrloc(&ul) < 0) { - return -1; - } - /* init timer lists*/ if (init_ro_timer(ro_session_ontimeout) != 0) { LM_ERR("cannot init timer list\n"); @@ -251,15 +237,6 @@ static int mod_init(void) { LM_ERR("failed to register timer \n"); return -1; } - - - - /*Register for callback of URECORD being deleted - so we can send a SAR*/ - - if (ul.register_ulcb == NULL) { - LM_ERR("Could not import ul_register_ulcb\n"); - return -1; - } if (ims_charging_init_counters() != 0) { LM_ERR("Failed to register counters for ims_charging module\n"); diff --git a/modules/ims_charging/ro_session_hash.h b/modules/ims_charging/ro_session_hash.h index 422e502e23b..e8803ea332d 100644 --- a/modules/ims_charging/ro_session_hash.h +++ b/modules/ims_charging/ro_session_hash.h @@ -10,7 +10,6 @@ #include "ro_timer.h" #include "../../mem/shm_mem.h" -#include "../ims_usrloc_scscf/usrloc.h" #include "ims_charging_stats.h" #include From 35e71ff8ae434e90baae00801985bdfebcb07d0d Mon Sep 17 00:00:00 2001 From: jaybeepee Date: Wed, 20 Jan 2016 12:07:56 +0200 Subject: [PATCH 137/142] modules/ims_qos: missing return statement --- modules/ims_qos/rx_str.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ims_qos/rx_str.c b/modules/ims_qos/rx_str.c index 136ea56a9d6..98a0bacfc77 100644 --- a/modules/ims_qos/rx_str.c +++ b/modules/ims_qos/rx_str.c @@ -107,7 +107,7 @@ int rx_send_str(str *rx_session_id) { // so just wait for STA or for Grace Timout to happen LM_DBG("Hmmm, auth session already in disconnected state\n"); cdpb.AAASessionsUnlock(auth->hash); - CSCF_RETURN_FALSE; + return CSCF_RETURN_FALSE; } LM_DBG("Creating STR\n"); From 0ce66908ee9da74806e2fa506ef98b5f9043e47c Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 20 Jan 2016 18:30:30 +0100 Subject: [PATCH 138/142] topoh: proper detection of cancel reply for processing - reported by Alex Balashov --- modules/topoh/topoh_mod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/topoh/topoh_mod.c b/modules/topoh/topoh_mod.c index 343a74521f9..fcdcc8c3a5c 100644 --- a/modules/topoh/topoh_mod.c +++ b/modules/topoh/topoh_mod.c @@ -331,7 +331,7 @@ int th_msg_received(void *data) { /* one Via in received reply -- it is for local generated request * - nothing to unhide unless is CANCEL/ACK */ - if((get_cseq(&msg)->method_id)&(METHOD_CANCEL)) + if(!((get_cseq(&msg)->method_id)&(METHOD_CANCEL))) goto done; } From edb11dd06b895e0b532c81ddc703420f7e5e81a1 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 20 Jan 2016 22:46:14 +0100 Subject: [PATCH 139/142] utils: bock indentations fixed --- modules/utils/utils.c | 292 +++++++++++++++++++++--------------------- 1 file changed, 146 insertions(+), 146 deletions(-) diff --git a/modules/utils/utils.c b/modules/utils/utils.c index b407742ccd0..3e914235634 100644 --- a/modules/utils/utils.c +++ b/modules/utils/utils.c @@ -104,30 +104,30 @@ int utils_forward(struct sip_msg *msg, int id, int proto); /* Exported functions */ static cmd_export_t cmds[] = { - {"http_query", (cmd_function)w_http_query, 2, fixup_http_query_get, - fixup_free_http_query_get, - REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE}, - {"http_query", (cmd_function)w_http_query_post, 3, fixup_http_query_post, - fixup_free_http_query_post, - REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE}, - {"http_query", (cmd_function)w_http_query_post_hdr, 4, fixup_http_query_post_hdr, - fixup_free_http_query_post_hdr, - REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE}, - {"xcap_auth_status", (cmd_function)xcap_auth_status, 2, fixup_pvar_pvar, - fixup_free_pvar_pvar, REQUEST_ROUTE}, - {0, 0, 0, 0, 0, 0} + {"http_query", (cmd_function)w_http_query, 2, fixup_http_query_get, + fixup_free_http_query_get, + REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE}, + {"http_query", (cmd_function)w_http_query_post, 3, fixup_http_query_post, + fixup_free_http_query_post, + REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE}, + {"http_query", (cmd_function)w_http_query_post_hdr, 4, fixup_http_query_post_hdr, + fixup_free_http_query_post_hdr, + REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE}, + {"xcap_auth_status", (cmd_function)xcap_auth_status, 2, fixup_pvar_pvar, + fixup_free_pvar_pvar, REQUEST_ROUTE}, + {0, 0, 0, 0, 0, 0} }; /* Exported parameters */ static param_export_t params[] = { - {"pres_db_url", PARAM_STR, &pres_db_url}, - {"xcap_table", PARAM_STR, &xcap_table}, - {"http_query_timeout", INT_PARAM, &http_query_timeout}, - {"http_response_trim", INT_PARAM, &http_response_trim}, - {"http_response_mode", INT_PARAM, &http_response_mode}, - {"forward_active", INT_PARAM, &forward_active}, - {0, 0, 0} + {"pres_db_url", PARAM_STR, &pres_db_url}, + {"xcap_table", PARAM_STR, &xcap_table}, + {"http_query_timeout", INT_PARAM, &http_query_timeout}, + {"http_response_trim", INT_PARAM, &http_response_trim}, + {"http_response_mode", INT_PARAM, &http_response_mode}, + {"forward_active", INT_PARAM, &forward_active}, + {0, 0, 0} }; static mi_export_t mi_cmds[] = { @@ -140,18 +140,18 @@ static mi_export_t mi_cmds[] = { /* Module interface */ struct module_exports exports = { - "utils", - DEFAULT_DLFLAGS, /* dlopen flags */ - cmds, /* Exported functions */ - params, /* Exported parameters */ - 0, /* exported statistics */ - mi_cmds, /* exported MI functions */ - 0, /* exported pseudo-variables */ - 0, /* extra processes */ - mod_init, /* module initialization function */ - 0, /* response function*/ - destroy, /* destroy function */ - child_init /* per-child init function */ + "utils", + DEFAULT_DLFLAGS, /* dlopen flags */ + cmds, /* Exported functions */ + params, /* Exported parameters */ + 0, /* exported statistics */ + mi_cmds, /* exported MI functions */ + 0, /* exported pseudo-variables */ + 0, /* extra processes */ + mod_init, /* module initialization function */ + 0, /* response function*/ + destroy, /* destroy function */ + child_init /* per-child init function */ }; @@ -192,51 +192,51 @@ static void destroy_shmlock(void) static void pres_db_close(void) { - if (pres_dbh) { - pres_dbf.close(pres_dbh); - pres_dbh = NULL; - } + if (pres_dbh) { + pres_dbf.close(pres_dbh); + pres_dbh = NULL; + } } static int pres_db_init(void) { - if (!pres_db_url.s || !pres_db_url.len) { - LM_INFO("xcap_auth_status function is disabled\n"); - return 0; - } - if (db_bind_mod(&pres_db_url, &pres_dbf) < 0) { - LM_ERR("can't bind database module\n"); - return -1; - } - if ((pres_dbh = pres_dbf.init(&pres_db_url)) == NULL) { - LM_ERR("can't connect to database\n"); - return -1; - } - if (db_check_table_version(&pres_dbf, pres_dbh, &xcap_table, - XCAP_TABLE_VERSION) < 0) { - LM_ERR("during table version check\n"); + if (!pres_db_url.s || !pres_db_url.len) { + LM_INFO("xcap_auth_status function is disabled\n"); + return 0; + } + if (db_bind_mod(&pres_db_url, &pres_dbf) < 0) { + LM_ERR("can't bind database module\n"); + return -1; + } + if ((pres_dbh = pres_dbf.init(&pres_db_url)) == NULL) { + LM_ERR("can't connect to database\n"); + return -1; + } + if (db_check_table_version(&pres_dbf, pres_dbh, &xcap_table, + XCAP_TABLE_VERSION) < 0) { + LM_ERR("during table version check\n"); + pres_db_close(); + return -1; + } pres_db_close(); - return -1; - } - pres_db_close(); - return 0; + return 0; } static int pres_db_open(void) { - if (!pres_db_url.s || !pres_db_url.len) { + if (!pres_db_url.s || !pres_db_url.len) { + return 0; + } + if (pres_dbh) { + pres_dbf.close(pres_dbh); + } + if ((pres_dbh = pres_dbf.init(&pres_db_url)) == NULL) { + LM_ERR("can't connect to database\n"); + return -1; + } + if (pres_dbf.use_table(pres_dbh, &xcap_table) < 0) { + LM_ERR("in use_table: %.*s\n", xcap_table.len, xcap_table.s); + return -1; + } return 0; - } - if (pres_dbh) { - pres_dbf.close(pres_dbh); - } - if ((pres_dbh = pres_dbf.init(&pres_db_url)) == NULL) { - LM_ERR("can't connect to database\n"); - return -1; - } - if (pres_dbf.use_table(pres_dbh, &xcap_table) < 0) { - LM_ERR("in use_table: %.*s\n", xcap_table.len, xcap_table.s); - return -1; - } - return 0; } @@ -296,10 +296,10 @@ static int mod_init(void) /* presence database */ LM_DBG("pres_db_url=%s/%d/%p\n", ZSW(pres_db_url.s), pres_db_url.len, - pres_db_url.s); + pres_db_url.s); if(pres_db_init() < 0) { - return -1; + return -1; } return 0; @@ -312,7 +312,7 @@ static int child_init(int rank) if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN) return 0; /* do nothing for the main process */ - return pres_db_open(); + return pres_db_open(); } static void destroy(void) @@ -335,24 +335,24 @@ static void destroy(void) */ static int fixup_http_query_get(void** param, int param_no) { - if (param_no == 1) { - return fixup_spve_null(param, 1); - } - - if (param_no == 2) { - if (fixup_pvar_null(param, 1) != 0) { - LM_ERR("failed to fixup result pvar\n"); - return -1; + if (param_no == 1) { + return fixup_spve_null(param, 1); } - if (((pv_spec_t *)(*param))->setf == NULL) { - LM_ERR("result pvar is not writeble\n"); - return -1; + + if (param_no == 2) { + if (fixup_pvar_null(param, 1) != 0) { + LM_ERR("failed to fixup result pvar\n"); + return -1; + } + if (((pv_spec_t *)(*param))->setf == NULL) { + LM_ERR("result pvar is not writeble\n"); + return -1; + } + return 0; } - return 0; - } - LM_ERR("invalid parameter number <%d>\n", param_no); - return -1; + LM_ERR("invalid parameter number <%d>\n", param_no); + return -1; } /* @@ -360,16 +360,16 @@ static int fixup_http_query_get(void** param, int param_no) */ static int fixup_free_http_query_get(void** param, int param_no) { - if (param_no == 1) { - return fixup_free_spve_null(param, 1); - } - - if (param_no == 2) { - return fixup_free_pvar_null(param, 1); - } - - LM_ERR("invalid parameter number <%d>\n", param_no); - return -1; + if (param_no == 1) { + return fixup_free_spve_null(param, 1); + } + + if (param_no == 2) { + return fixup_free_pvar_null(param, 1); + } + + LM_ERR("invalid parameter number <%d>\n", param_no); + return -1; } @@ -379,24 +379,24 @@ static int fixup_free_http_query_get(void** param, int param_no) */ static int fixup_http_query_post(void** param, int param_no) { - if ((param_no == 1) || (param_no == 2)) { - return fixup_spve_null(param, 1); - } - - if (param_no == 3) { - if (fixup_pvar_null(param, 1) != 0) { - LM_ERR("failed to fixup result pvar\n"); - return -1; + if ((param_no == 1) || (param_no == 2)) { + return fixup_spve_null(param, 1); } - if (((pv_spec_t *)(*param))->setf == NULL) { - LM_ERR("result pvar is not writeble\n"); - return -1; + + if (param_no == 3) { + if (fixup_pvar_null(param, 1) != 0) { + LM_ERR("failed to fixup result pvar\n"); + return -1; + } + if (((pv_spec_t *)(*param))->setf == NULL) { + LM_ERR("result pvar is not writeble\n"); + return -1; + } + return 0; } - return 0; - } - LM_ERR("invalid parameter number <%d>\n", param_no); - return -1; + LM_ERR("invalid parameter number <%d>\n", param_no); + return -1; } /* @@ -405,24 +405,24 @@ static int fixup_http_query_post(void** param, int param_no) */ static int fixup_http_query_post_hdr(void** param, int param_no) { - if ((param_no >= 1) && (param_no <= 3)) { - return fixup_spve_null(param, 1); - } - - if (param_no == 4) { - if (fixup_pvar_null(param, 1) != 0) { - LM_ERR("failed to fixup result pvar\n"); - return -1; + if ((param_no >= 1) && (param_no <= 3)) { + return fixup_spve_null(param, 1); } - if (((pv_spec_t *)(*param))->setf == NULL) { - LM_ERR("result pvar is not writeble\n"); - return -1; + + if (param_no == 4) { + if (fixup_pvar_null(param, 1) != 0) { + LM_ERR("failed to fixup result pvar\n"); + return -1; + } + if (((pv_spec_t *)(*param))->setf == NULL) { + LM_ERR("result pvar is not writeble\n"); + return -1; + } + return 0; } - return 0; - } - LM_ERR("invalid parameter number <%d>\n", param_no); - return -1; + LM_ERR("invalid parameter number <%d>\n", param_no); + return -1; } /* @@ -430,16 +430,16 @@ static int fixup_http_query_post_hdr(void** param, int param_no) */ static int fixup_free_http_query_post(void** param, int param_no) { - if ((param_no == 1) || (param_no == 2)) { - return fixup_free_spve_null(param, 1); - } - - if (param_no == 3) { - return fixup_free_pvar_null(param, 1); - } - - LM_ERR("invalid parameter number <%d>\n", param_no); - return -1; + if ((param_no == 1) || (param_no == 2)) { + return fixup_free_spve_null(param, 1); + } + + if (param_no == 3) { + return fixup_free_pvar_null(param, 1); + } + + LM_ERR("invalid parameter number <%d>\n", param_no); + return -1; } /* @@ -447,16 +447,16 @@ static int fixup_free_http_query_post(void** param, int param_no) */ static int fixup_free_http_query_post_hdr(void** param, int param_no) { - if ((param_no >= 1) && (param_no <= 3)) { - return fixup_free_spve_null(param, 1); - } - - if (param_no == 4) { - return fixup_free_pvar_null(param, 1); - } - - LM_ERR("invalid parameter number <%d>\n", param_no); - return -1; + if ((param_no >= 1) && (param_no <= 3)) { + return fixup_free_spve_null(param, 1); + } + + if (param_no == 4) { + return fixup_free_pvar_null(param, 1); + } + + LM_ERR("invalid parameter number <%d>\n", param_no); + return -1; } /* From 760c1d55dfa53e09ab1d6b87e157ea61fba24c24 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 20 Jan 2016 23:32:58 +0100 Subject: [PATCH 140/142] crypto: new module offering various cryptographic functions - AES encryption/decryption functions - encrypted data is given as base64 string to be able to use it with config and sip messages --- modules/crypto/Makefile | 37 +++ modules/crypto/README | 106 ++++++++ modules/crypto/crypto_mod.c | 383 ++++++++++++++++++++++++++++ modules/crypto/doc/Makefile | 4 + modules/crypto/doc/crypto.xml | 37 +++ modules/crypto/doc/crypto_admin.xml | 107 ++++++++ 6 files changed, 674 insertions(+) create mode 100644 modules/crypto/Makefile create mode 100644 modules/crypto/README create mode 100644 modules/crypto/crypto_mod.c create mode 100644 modules/crypto/doc/Makefile create mode 100644 modules/crypto/doc/crypto.xml create mode 100644 modules/crypto/doc/crypto_admin.xml diff --git a/modules/crypto/Makefile b/modules/crypto/Makefile new file mode 100644 index 00000000000..8beabccdbc5 --- /dev/null +++ b/modules/crypto/Makefile @@ -0,0 +1,37 @@ +# +# +# WARNING: do not run this directly, it should be run by the master Makefile + +include ../../Makefile.defs +auto_gen= +NAME=crypto.so + +ifeq ($(CROSS_COMPILE),) +SSL_BUILDER=$(shell \ + if pkg-config --exists libssl; then \ + echo 'pkg-config libssl'; \ + fi) + +ifneq ($(SSL_BUILDER),) +SSL_BUILDER+=$(shell \ + if pkg-config --exists libcrypto; then \ + echo 'libcrypto'; \ + fi) +endif + +endif + +ifneq ($(SSL_BUILDER),) + DEFS += $(shell $(SSL_BUILDER) --cflags) + LIBS += $(shell $(SSL_BUILDER) --libs) +else + DEFS += -I$(LOCALBASE)/ssl/include + LIBS += -L$(LOCALBASE)/lib -L$(LOCALBASE)/ssl/lib \ + -L$(LOCALBASE)/lib64 -L$(LOCALBASE)/ssl/lib64 \ + -lssl -lcrypto +endif + +DEFS+=-DKAMAILIO_MOD_INTERFACE + +include ../../Makefile.modules + diff --git a/modules/crypto/README b/modules/crypto/README new file mode 100644 index 00000000000..79608b4a3aa --- /dev/null +++ b/modules/crypto/README @@ -0,0 +1,106 @@ +CRYPTO Module + +Daniel-Constantin Mierla + + + +Edited by + +Daniel-Constantin Mierla + + + + Copyright © 2016 asipto.com + __________________________________________________________________ + + Table of Contents + + 1. Admin Guide + + 1. Overview + 2. Dependencies + + 2.1. Kamailio Modules + 2.2. External Libraries or Applications + + 3. Functions + + 3.1. crypto_aes_encrypt(text, key, res) + 3.2. crypto_aes_decrypt(text, key, res) + + List of Examples + + 1.1. crypto_aes_encrypt usage + 1.2. crypto_aes_decrypt usage + +Chapter 1. Admin Guide + + Table of Contents + + 1. Overview + 2. Dependencies + + 2.1. Kamailio Modules + 2.2. External Libraries or Applications + + 3. Functions + + 3.1. crypto_aes_encrypt(text, key, res) + 3.2. crypto_aes_decrypt(text, key, res) + +1. Overview + + This module provides various cryptography tools for use in Kamailio + configuration file. + + It relies on OpenSSL libraries for cryptographic operations (libssl, + libcrypto). + +2. Dependencies + + 2.1. Kamailio Modules + 2.2. External Libraries or Applications + +2.1. Kamailio Modules + + The following modules must be loaded before this module: + * none. + +2.2. External Libraries or Applications + + The following libraries or applications must be installed before + running Kamailio with this module loaded: + * libcrypto - part of OpenSSL project + +3. Functions + + 3.1. crypto_aes_encrypt(text, key, res) + 3.2. crypto_aes_decrypt(text, key, res) + +3.1. crypto_aes_encrypt(text, key, res) + + Encrypts the text with the key using AES encryption algorithm. The + result is encoded in base64 format and stored in res. The parameter res + must be a read-write variables. The parameters text and key can be + static strings or strings with variables (dynamic strings). + + This function can be used from ANY_ROUTE. + + Example 1.1. crypto_aes_encrypt usage +... +crypto_aes_encrypt("$rb", "my-secret-key", "$var(encrypted)"); +... + +3.2. crypto_aes_decrypt(text, key, res) + + Decrypts the text with the key using AES encryption algorithm. The text + has to be encoded in base64 format. The parameter res must be a + read-write variables. The parameters text and key can be static strings + or strings with variables (dynamic strings). + + This function can be used from ANY_ROUTE. + + Example 1.2. crypto_aes_decrypt usage +... +crypto_aes_decrypt("$var(encrypted)", "my-secret-key", "$var(text)"); +... diff --git a/modules/crypto/crypto_mod.c b/modules/crypto/crypto_mod.c new file mode 100644 index 00000000000..9decce7c2f6 --- /dev/null +++ b/modules/crypto/crypto_mod.c @@ -0,0 +1,383 @@ +/** + * Copyright (C) 2011 Daniel-Constantin Mierla (asipto.com) + * + * This file is part of Kamailio, a free SIP server. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include + +#include "../../sr_module.h" +#include "../../dprint.h" +#include "../../mod_fix.h" +#include "../../pvapi.h" +#include "../../lvalue.h" +#include "../../basex.h" + +#include + +#define AES_BLOCK_SIZE 256 + +MODULE_VERSION + +int crypto_aes_init(unsigned char *key_data, int key_data_len, + unsigned char *salt, EVP_CIPHER_CTX *e_ctx, EVP_CIPHER_CTX *d_ctx); +unsigned char *crypto_aes_encrypt(EVP_CIPHER_CTX *e, unsigned char *plaintext, + int *len); +unsigned char *crypto_aes_decrypt(EVP_CIPHER_CTX *e, unsigned char *ciphertext, + int *len); + +static int mod_init(void); +static int child_init(int); +static void mod_destroy(void); + +static int w_crypto_aes_encrypt(sip_msg_t* msg, char* inb, char* keyb, char* outb); +static int fixup_crypto_aes_encrypt(void** param, int param_no); +static int w_crypto_aes_decrypt(sip_msg_t* msg, char* inb, char* keyb, char* outb); +static int fixup_crypto_aes_decrypt(void** param, int param_no); + + +static cmd_export_t cmds[]={ + {"crypto_aes_encrypt", (cmd_function)w_crypto_aes_encrypt, 3, + fixup_crypto_aes_encrypt, 0, ANY_ROUTE}, + {"crypto_aes_decrypt", (cmd_function)w_crypto_aes_decrypt, 3, + fixup_crypto_aes_decrypt, 0, ANY_ROUTE}, + {0, 0, 0, 0, 0, 0} +}; + +static param_export_t params[]={ + {0, 0, 0} +}; + +struct module_exports exports = { + "crypto", + DEFAULT_DLFLAGS, /* dlopen flags */ + cmds, + params, + 0, + 0, /* exported MI functions */ + 0, /* exported pseudo-variables */ + 0, /* extra processes */ + mod_init, /* module initialization function */ + 0, /* response function */ + mod_destroy, /* destroy function */ + child_init /* per child init function */ +}; + + +/** + * @brief Initialize crypto module function + */ +static int mod_init(void) +{ + return 0; +} + +/** + * @brief Initialize crypto module children + */ +static int child_init(int rank) +{ + return 0; +} + +/** + * destroy module function + */ +static void mod_destroy(void) +{ + return; +} + +/** + * + */ +static int w_crypto_aes_encrypt(sip_msg_t* msg, char* inb, char* keyb, char* outb) +{ + str ins; + str keys; + pv_spec_t *dst; + pv_value_t val; + EVP_CIPHER_CTX en; + str etext; + unsigned char salt[] = {1,2,3,4,5,6,7,8}; + + if (fixup_get_svalue(msg, (gparam_t*)inb, &ins) != 0) { + LM_ERR("cannot get input value\n"); + return -1; + } + if (fixup_get_svalue(msg, (gparam_t*)keyb, &keys) != 0) { + LM_ERR("cannot get key value\n"); + return -1; + } + dst = (pv_spec_t*)outb; + + /* gen key and iv. init the cipher ctx object */ + if (crypto_aes_init((unsigned char *)keys.s, keys.len, salt, &en, NULL)) { + LM_ERR("couldn't initialize AES cipher\n"); + return -1; + } + etext.len = ins.len; + etext.s = (char *)crypto_aes_encrypt(&en, (unsigned char *)ins.s, &etext.len); + + memset(&val, 0, sizeof(pv_value_t)); + val.rs.s = pv_get_buffer(); + val.rs.len = base64_enc((unsigned char *)etext.s, etext.len, + (unsigned char *)val.rs.s, pv_get_buffer_size()-1); + if (val.rs.len < 0) { + LM_ERR("base64 output of encrypted value is too large (need %d)\n", + -val.rs.len); + goto error; + } + LM_DBG("base64 encrypted result: [%.*s]\n", val.rs.len, val.rs.s); + val.flags = PV_VAL_STR; + dst->setf(msg, &dst->pvp, (int)EQ_T, &val); + + free(etext.s); + EVP_CIPHER_CTX_cleanup(&en); + return 1; + +error: + free(etext.s); + EVP_CIPHER_CTX_cleanup(&en); + return -1; +} + +/** + * + */ +static int fixup_crypto_aes_encrypt(void** param, int param_no) +{ + if(param_no==1 || param_no==2) { + if(fixup_spve_null(param, 1)<0) + return -1; + return 0; + } else if(param_no==3) { + if (fixup_pvar_null(param, 1) != 0) { + LM_ERR("failed to fixup result pvar\n"); + return -1; + } + if (((pv_spec_t *)(*param))->setf == NULL) { + LM_ERR("result pvar is not writeble\n"); + return -1; + } + } + return 0; +} + +/** + * + */ +static int w_crypto_aes_decrypt(sip_msg_t* msg, char* inb, char* keyb, char* outb) +{ + return 1; +} + +/** + * + */ +static int fixup_crypto_aes_decrypt(void** param, int param_no) +{ + if(param_no==1 || param_no==2) { + if(fixup_spve_null(param, 1)<0) + return -1; + return 0; + } else if(param_no==3) { + if (fixup_pvar_null(param, 1) != 0) { + LM_ERR("failed to fixup result pvar\n"); + return -1; + } + if (((pv_spec_t *)(*param))->setf == NULL) { + LM_ERR("result pvar is not writeble\n"); + return -1; + } + } + return 0; +} + + +/** + * Create an 256 bit key and IV using the supplied key_data and salt. + * Fills in the encryption and decryption ctx objects and returns 0 on success + */ +int crypto_aes_init(unsigned char *key_data, int key_data_len, + unsigned char *salt, EVP_CIPHER_CTX *e_ctx, EVP_CIPHER_CTX *d_ctx) +{ + int i, nrounds = 5; + unsigned char key[32], iv[32]; + + /* + * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash + * the supplied key material. + * nrounds is the number of times the we hash the material. More rounds + * are more secure but slower. + */ + i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, + key_data, key_data_len, nrounds, key, iv); + if (i != 32) { + LM_ERR("key size is %d bits - should be 256 bits\n", i); + return -1; + } + + for(int x = 0; x<32; ++x) + LM_DBG("key: %x iv: %x \n", key[x], iv[x]); + + for(int x = 0; x<8; ++x) + LM_DBG("salt: %x\n", salt[x]); + + if(e_ctx) { + EVP_CIPHER_CTX_init(e_ctx); + EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv); + } + if(d_ctx) { + EVP_CIPHER_CTX_init(d_ctx); + EVP_DecryptInit_ex(d_ctx, EVP_aes_256_cbc(), NULL, key, iv); + } + + return 0; +} + +/* + * Encrypt *len bytes of data + * All data going in & out is considered binary (unsigned char[]) + */ +unsigned char *crypto_aes_encrypt(EVP_CIPHER_CTX *e, unsigned char *plaintext, + int *len) +{ + /* max ciphertext len for a n bytes of plaintext is + * n + AES_BLOCK_SIZE -1 bytes */ + int c_len = *len + AES_BLOCK_SIZE - 1, f_len = 0; + unsigned char *ciphertext = (unsigned char *)malloc(c_len); + + /* allows reusing of 'e' for multiple encryption cycles */ + if(!EVP_EncryptInit_ex(e, NULL, NULL, NULL, NULL)){ + LM_ERR("failure in EVP_EncryptInit_ex \n"); + return NULL; + } + + /* update ciphertext, c_len is filled with the length of ciphertext + * generated, *len is the size of plaintext in bytes */ + if(!EVP_EncryptUpdate(e, ciphertext, &c_len, plaintext, *len)){ + LM_ERR("failure in EVP_EncryptUpdate \n"); + return NULL; + } + + /* update ciphertext with the final remaining bytes */ + if(!EVP_EncryptFinal_ex(e, ciphertext+c_len, &f_len)){ + LM_ERR("failure in EVP_EncryptFinal_ex \n"); + return NULL; + } + + *len = c_len + f_len; + return ciphertext; +} + +/* + * Decrypt *len bytes of ciphertext + */ +unsigned char *crypto_aes_decrypt(EVP_CIPHER_CTX *e, unsigned char *ciphertext, + int *len) +{ + /* plaintext will always be equal to or lesser than length of ciphertext*/ + int p_len = *len, f_len = 0; + unsigned char *plaintext = (unsigned char *)malloc(p_len); + + if(!EVP_DecryptInit_ex(e, NULL, NULL, NULL, NULL)){ + LM_ERR("failure in EVP_DecryptInit_ex \n"); + return NULL; + } + + if(!EVP_DecryptUpdate(e, plaintext, &p_len, ciphertext, *len)){ + LM_ERR("failure in EVP_DecryptUpdate\n"); + return NULL; + } + + if(!EVP_DecryptFinal_ex(e, plaintext+p_len, &f_len)){ + LM_ERR("failure in EVP_DecryptFinal_ex\n"); + return NULL; + } + + *len = p_len + f_len; + return plaintext; +} + +/** + * testing function + */ +int crypto_aes_test(void) +{ + /* "opaque" encryption, decryption ctx structures + * that libcrypto uses to record status of enc/dec operations */ + EVP_CIPHER_CTX en, de; + + + /* The salt paramter is used as a salt in the derivation: + * it should point to an 8 byte buffer or NULL if no salt is used. */ + unsigned char salt[] = {1,2,3,4,5,6,7,8}; + + unsigned char *key_data; + int key_data_len, i; + char *input[] = {"Kamailio - The Open Source SIP Server", + "Thank you for flying Kamailio!", + "100 Trying\nYour call is important to us", + NULL + }; + + /* the key_data for testing */ + key_data = (unsigned char *)"kamailio-sip-server"; + key_data_len = strlen((const char *)key_data); + + /* gen key and iv. init the cipher ctx object */ + if (crypto_aes_init(key_data, key_data_len, salt, &en, &de)) { + LM_ERR("couldn't initialize AES cipher\n"); + return -1; + } + + /* encrypt and decrypt each input string and compare with the original */ + for (i = 0; input[i]; i++) { + char *plaintext; + unsigned char *ciphertext; + int olen, len; + + /* The enc/dec functions deal with binary data and not C strings. + * strlen() will return length of the string without counting the '\0' + * string marker. We always pass in the marker byte to the + * encrypt/decrypt functions so that after decryption we end up with + * a legal C string */ + olen = len = strlen(input[i])+1; + + ciphertext = crypto_aes_encrypt(&en, (unsigned char *)input[i], &len); + plaintext = (char *)crypto_aes_decrypt(&de, ciphertext, &len); + + if (strncmp(plaintext, input[i], olen)) + LM_ERR("FAIL: enc/dec failed for \"%s\"\n", input[i]); + else + LM_NOTICE("OK: enc/dec ok for \"%s\"\n", plaintext); + + free(ciphertext); + free(plaintext); + } + + EVP_CIPHER_CTX_cleanup(&de); + EVP_CIPHER_CTX_cleanup(&en); + + return 0; +} diff --git a/modules/crypto/doc/Makefile b/modules/crypto/doc/Makefile new file mode 100644 index 00000000000..b93e861ca56 --- /dev/null +++ b/modules/crypto/doc/Makefile @@ -0,0 +1,4 @@ +docs = crypto.xml + +docbook_dir = ../../../docbook +include $(docbook_dir)/Makefile.module diff --git a/modules/crypto/doc/crypto.xml b/modules/crypto/doc/crypto.xml new file mode 100644 index 00000000000..b53cf36a9b2 --- /dev/null +++ b/modules/crypto/doc/crypto.xml @@ -0,0 +1,37 @@ + + + +%docentities; + +]> + + + + CRYPTO Module + sip-router.org + + + Daniel-Constantin + Mierla + miconda@gmail.com + + + Daniel-Constantin + Mierla + miconda@gmail.com + + + + 2016 + asipto.com + + + + + + + + diff --git a/modules/crypto/doc/crypto_admin.xml b/modules/crypto/doc/crypto_admin.xml new file mode 100644 index 00000000000..da88e0f453a --- /dev/null +++ b/modules/crypto/doc/crypto_admin.xml @@ -0,0 +1,107 @@ + + + +%docentities; + +]> + + + + + &adminguide; + +
+ Overview + + This module provides various cryptography tools for use + in &kamailio; configuration file. + + + It relies on OpenSSL libraries for cryptographic operations + (libssl, libcrypto). + +
+ +
+ Dependencies +
+ &kamailio; Modules + + The following modules must be loaded before this module: + + + + none. + + + + +
+
+ External Libraries or Applications + + The following libraries or applications must be installed before running + &kamailio; with this module loaded: + + + + libcrypto - part of OpenSSL project + + + + +
+
+ +
+ Functions +
+ + <function moreinfo="none">crypto_aes_encrypt(text, key, res)</function> + + + Encrypts the text with the key using AES encryption algorithm. The + result is encoded in base64 format and stored in res. The parameter + res must be a read-write variables. The parameters text and key can + be static strings or strings with variables (dynamic strings). + + + This function can be used from ANY_ROUTE. + + + <function>crypto_aes_encrypt</function> usage + +... +crypto_aes_encrypt("$rb", "my-secret-key", "$var(encrypted)"); +... + + +
+ +
+ + <function moreinfo="none">crypto_aes_decrypt(text, key, res)</function> + + + Decrypts the text with the key using AES encryption algorithm. The + text has to be encoded in base64 format. The parameter + res must be a read-write variables. The parameters text and key can + be static strings or strings with variables (dynamic strings). + + + This function can be used from ANY_ROUTE. + + + <function>crypto_aes_decrypt</function> usage + +... +crypto_aes_decrypt("$var(encrypted)", "my-secret-key", "$var(text)"); +... + + +
+
+
From 2d612982966d87ed1cc6f56b10886fe89a1c10c4 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 20 Jan 2016 23:35:49 +0100 Subject: [PATCH 141/142] Makefile.groups: added crypto module to tls group - dependency on libssl --- Makefile.groups | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.groups b/Makefile.groups index 96b36056bd3..c7895dbb93b 100644 --- a/Makefile.groups +++ b/Makefile.groups @@ -90,7 +90,7 @@ mod_list_purple=purple mod_list_memcached=memcached # - modules depending on openssl library -mod_list_tlsdeps=auth_identity tls +mod_list_tlsdeps=auth_identity crypto tls # - modules depending on openssl library mod_list_outbound=outbound From 1d28d1fd5485895cd8d7895a3ab410814d57b6bb Mon Sep 17 00:00:00 2001 From: "Olle E. Johansson" Date: Thu, 21 Jan 2016 08:44:49 +0100 Subject: [PATCH 142/142] curl Small TODO update based on e-mail to sr-dev --- modules/curl/TODO.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/curl/TODO.txt b/modules/curl/TODO.txt index 2bb134f099d..1635b0cb612 100644 --- a/modules/curl/TODO.txt +++ b/modules/curl/TODO.txt @@ -48,6 +48,7 @@ The curl module - todo - Async - event_route when done + (with and without suspending transaction) Need background task process to run curl request event_route[curl:connectioncomplete] $curlcon == connection