浏览代码

Merge branch 'master' of ssh://git.sip-router.org/kamailio

* 'master' of ssh://git.sip-router.org/kamailio:
  permissions: fixed previous commit which used invalid variable
  presence_dialoginfo: handle all states to get most relevant xml
  tls: the pointer of cfg structure
  websocket: store sub protocol value for later use in encode_and_send_ws_frame()
  htable: free temporary slots used to reload hash table via rpc command
  htable: use system malloc for temporary allocation of hash table realod slots
  permissions: refreshed the README file
  permissions: note about peer tag mode that applies only for allow_trusted()
  permissions: set peer tag avp for allow_address_group()
Hugh Waite 11 年之前
父节点
当前提交
3a5af040ed

+ 30 - 3
modules/htable/htable.c

@@ -490,7 +490,8 @@ static struct mi_root* ht_mi_reload(struct mi_root* cmd_tree, void* param)
 		return init_mi_tree( 500, "no such hash table", 18);
 	}
 	memcpy(&nht, ht, sizeof(ht_t));
-	nht.entries = (ht_entry_t*)pkg_malloc(nht.htsize*sizeof(ht_entry_t));
+	/* it's temporary operation - use system malloc */
+	nht.entries = (ht_entry_t*)malloc(nht.htsize*sizeof(ht_entry_t));
 	if(nht.entries == NULL)
 	{
 		ht_db_close_con();
@@ -500,6 +501,18 @@ static struct mi_root* ht_mi_reload(struct mi_root* cmd_tree, void* param)
 
 	if(ht_db_load_table(&nht, &ht->dbtable, 0)<0)
 	{
+		/* free any entry set if it was a partial load */
+		for(i=0; i<nht.htsize; i++)
+		{
+			first = nht.entries[i].first;
+			while(first)
+			{
+				it = first;
+				first = first->next;
+				ht_cell_free(it);
+			}
+		}
+		free(nht.entries);
 		ht_db_close_con();
 		return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
 	}
@@ -525,7 +538,7 @@ static struct mi_root* ht_mi_reload(struct mi_root* cmd_tree, void* param)
 			ht_cell_free(it);
 		}
 	}
-	pkg_free(nht.entries);
+	free(nht.entries);
 	ht_db_close_con();
 	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
 }
@@ -1036,7 +1049,8 @@ static void htable_rpc_reload(rpc_t* rpc, void* c)
 
 
 	memcpy(&nht, ht, sizeof(ht_t));
-	nht.entries = (ht_entry_t*)shm_malloc(nht.htsize*sizeof(ht_entry_t));
+	/* it's temporary operation - use system malloc */
+	nht.entries = (ht_entry_t*)malloc(nht.htsize*sizeof(ht_entry_t));
 	if(nht.entries == NULL)
 	{
 		ht_db_close_con();
@@ -1047,6 +1061,18 @@ static void htable_rpc_reload(rpc_t* rpc, void* c)
 
 	if(ht_db_load_table(&nht, &ht->dbtable, 0)<0)
 	{
+		/* free any entry set if it was a partial load */
+		for(i=0; i<nht.htsize; i++)
+		{
+			first = nht.entries[i].first;
+			while(first)
+			{
+				it = first;
+				first = first->next;
+				ht_cell_free(it);
+			}
+		}
+		free(nht.entries);
 		ht_db_close_con();
 		rpc->fault(c, 500, "Mtree reload failed");
 		return;
@@ -1073,6 +1099,7 @@ static void htable_rpc_reload(rpc_t* rpc, void* c)
 			ht_cell_free(it);
 		}
 	}
+	free(nht.entries);
 	ht_db_close_con();
 	return;
 }

+ 59 - 58
modules/permissions/README

@@ -14,9 +14,9 @@ Edited by
 
 Juha Heinanen
 
-   Copyright © 2003 Miklos Tirpak
+   Copyright © 2003 Miklos Tirpak
 
-   Copyright © 2006-2008 Juha Heinanen
+   Copyright © 2006-2008 Juha Heinanen
      __________________________________________________________________
 
    Table of Contents
@@ -250,7 +250,7 @@ Chapter 1. Admin Guide
 
    Function for registration checking is called allow_register and the
    algorithm is very similar to the algorithm described in Section 1.1,
-   “Call Routing�. The only difference is in the way how pairs are
+   "Call Routing". The only difference is in the way how pairs are
    created.
 
    Instead of From header field the function uses To header field because
@@ -261,8 +261,8 @@ Chapter 1. Admin Guide
    Thus, pairs used in matching will look like this: (To, Contact 1), (To,
    Contact 2), (To, Contact 3), and so on..
 
-   The algorithm of matching is same as described in Section 1.1, “Call
-   Routing�.
+   The algorithm of matching is same as described in Section 1.1, "Call
+   Routing".
 
 1.3. URI Permissions
 
@@ -387,7 +387,7 @@ Chapter 1. Admin Guide
    specify full pathname then the directory in which is the main config
    file is located will be used.
 
-   Default value is “permissions.allow�.
+   Default value is "permissions.allow".
 
    Example 1.1. Set default_allow_file parameter
 ...
@@ -400,7 +400,7 @@ modparam("permissions", "default_allow_file", "/etc/permissions.allow")
    without parameters. If you don't specify full pathname then the
    directory in which the main config file is located will be used.
 
-   Default value is “permissions.deny�.
+   Default value is "permissions.deny".
 
    Example 1.2. Set default_deny_file parameter
 ...
@@ -435,7 +435,7 @@ Note
 
    Including leading dot.
 
-   Default value is “.allow�.
+   Default value is ".allow".
 
    Example 1.4. Set allow_suffix parameter
 ...
@@ -452,7 +452,7 @@ Note
 
    Including leading dot.
 
-   Default value is “.deny�.
+   Default value is ".deny".
 
    Example 1.5. Set deny_suffix parameter
 ...
@@ -464,7 +464,7 @@ modparam("permissions", "deny_suffix", ".deny")
    This is URL of the database to be used to store rules used by
    allow_trusted function.
 
-   Default value is “NULL�.
+   Default value is "NULL".
 
    Example 1.6. Set db_url parameter
 ...
@@ -476,7 +476,7 @@ modparam("permissions", "db_url", "dbdriver://username:password@dbhost/dbname")
    Name of database table containing IP subnets and DNS domain names used
    by allow_address and allow_source_address functions.
 
-   Default value is “address�.
+   Default value is "address".
 
    Example 1.7. Set address_table parameter
 ...
@@ -488,7 +488,7 @@ modparam("permissions", "address_table", "addr")
    Name of address table column containing group identifier of the
    address.
 
-   Default value is “grp�.
+   Default value is "grp".
 
    Example 1.8. Set grp_col parameter
 ...
@@ -499,7 +499,7 @@ modparam("permissions", "grp_col", "group_id")
 
    Name of address table column containing IP address part of the address.
 
-   Default value is “ip_addr�.
+   Default value is "ip_addr".
 
    Example 1.9. Set ip_addr_col parameter
 ...
@@ -511,7 +511,7 @@ modparam("permissions", "ip_addr_col", "ip_address")
    Name of address table column containing network mask of the address.
    Possible values are 0-32.
 
-   Default value is “mask�.
+   Default value is "mask".
 
    Example 1.10. Set mask_col parameter
 ...
@@ -522,7 +522,7 @@ modparam("permissions", "mask_col", "subnet_length")
 
    Name of address table column containing port part of the address.
 
-   Default value is “port�.
+   Default value is "port".
 
    Example 1.11. Set port_col parameter
 ...
@@ -546,7 +546,7 @@ modparam("permissions", "db_mode", 1)
    Name of database table containing matching rules used by allow_trusted
    function.
 
-   Default value is “trusted�.
+   Default value is "trusted".
 
    Example 1.13. Set trusted_table parameter
 ...
@@ -558,7 +558,7 @@ modparam("permissions", "trusted_table", "pbx")
    Name of trusted table column containing source IP address that is
    matched against source IP address of received request.
 
-   Default value is “src_ip�.
+   Default value is "src_ip".
 
    Example 1.14. Set source_col parameter
 ...
@@ -569,10 +569,10 @@ modparam("permissions", "source_col", "source_ip_address")
 
    Name of trusted table column containing transport protocol that is
    matched against transport protocol of received request. Possible values
-   that can be stored in proto_col are “any�, “udp�, “tcp�, “tls�, “sctp�,
-   and “none�. Value “any� matches always and value “none� never.
+   that can be stored in proto_col are "any", "udp", "tcp", "tls", "sctp",
+   and "none". Value "any" matches always and value "none" never.
 
-   Default value is “proto�.
+   Default value is "proto".
 
    Example 1.15. Set proto_col parameter
 ...
@@ -584,7 +584,7 @@ modparam("permissions", "proto_col", "transport")
    Name of trusted table column containing regular expression that is
    matched against From URI.
 
-   Default value is “from_pattern�.
+   Default value is "from_pattern".
 
    Example 1.16. Set from_col parameter
 ...
@@ -597,7 +597,7 @@ modparam("permissions", "from_col", "regexp")
    added as value to peer_tag AVP if peer_tag AVP has been defined and if
    the address or peer matches.
 
-   Default value is “tag�.
+   Default value is "tag".
 
    Example 1.17. Set tag_col parameter
 ...
@@ -609,7 +609,7 @@ modparam("permissions", "tag_col", "peer_tag")
    If defined, the AVP will be set as side effect of allow_trusted() call
    to not NULL tag column value of the matching peer.
 
-   Default value is “undefined�.
+   Default value is "undefined".
 
    Example 1.18. Set peer_tag_avp parameter
 ...
@@ -620,9 +620,10 @@ modparam("permissions", "peer_tag_avp", "$avp(i:707)")
 
    Tag mode for allow_trusted(). 0 sets only the tag of the first match. 1
    adds the tags of all matches to the avp. In addition the return value
-   of allow_trusted() is the number of matches.
+   of allow_trusted() is the number of matches. This parameter is not used
+   for address table matching functions.
 
-   Default value is “0�.
+   Default value is "0".
 
    Example 1.19. Set peer_tag_mode parameter
 ...
@@ -643,10 +644,10 @@ modparam("permissions", "peer_tag_mode", "1")
    4.10. allow_address_group(addr, port)
    4.11. allow_trusted([src_ip_pvar, proto_pvar])
 
-4.1.  allow_routing()
+4.1. allow_routing()
 
    Returns true if all pairs constructed as described in Section 1.1,
-   “Call Routing� have appropriate permissions according to the
+   "Call Routing" have appropriate permissions according to the
    configuration files. This function uses default configuration files
    specified in default_allow_file and default_deny_file.
 
@@ -659,10 +660,10 @@ if (allow_routing()) {
 };
 ...
 
-4.2.  allow_routing(basename)
+4.2. allow_routing(basename)
 
    Returns true if all pairs constructed as described in Section 1.1,
-   “Call Routing� have appropriate permissions according to the
+   "Call Routing" have appropriate permissions according to the
    configuration files given as parameters.
 
    Meaning of the parameters is as follows:
@@ -682,10 +683,10 @@ if (allow_routing("basename")) {
 };
 ...
 
-4.3.  allow_routing(allow_file,deny_file)
+4.3. allow_routing(allow_file,deny_file)
 
    Returns true if all pairs constructed as described in Section 1.1,
-   “Call Routing� have appropriate permissions according to the
+   "Call Routing" have appropriate permissions according to the
    configuration files given as parameters.
 
    Meaning of the parameters is as follows:
@@ -707,10 +708,10 @@ if (allow_routing("rules.allow", "rules.deny")) {
 };
 ...
 
-4.4.  allow_register(basename)
+4.4. allow_register(basename)
 
    The function returns true if all pairs constructed as described in
-   Section 1.2, “Registration Permissions� have appropriate permissions
+   Section 1.2, "Registration Permissions" have appropriate permissions
    according to the configuration files given as parameters.
 
    Meaning of the parameters is as follows:
@@ -735,10 +736,10 @@ if (method=="REGISTER") {
 };
 ...
 
-4.5.  allow_register(allow_file, deny_file)
+4.5. allow_register(allow_file, deny_file)
 
    The function returns true if all pairs constructed as described in
-   Section 1.2, “Registration Permissions� have appropriate permissions
+   Section 1.2, "Registration Permissions" have appropriate permissions
    according to the configuration files given as parameters.
 
    Meaning of the parameters is as follows:
@@ -765,10 +766,10 @@ if (method=="REGISTER") {
 };
 ...
 
-4.6.  allow_uri(basename, pvar)
+4.6. allow_uri(basename, pvar)
 
-   Returns true if the pair constructed as described in Section 1.3, “URI
-   Permissions� have appropriate permissions according to the
+   Returns true if the pair constructed as described in Section 1.3, "URI
+   Permissions" have appropriate permissions according to the
    configuration files specified by the parameter.
 
    Meaning of the parameter is as follows:
@@ -792,7 +793,7 @@ if (allow_uri("basename", "$avp(i:705)") {  // Check URI stored in $avp(i:705)
 };
 ...
 
-4.7.  allow_address(group_id, ip_addr_pvar, port_pvar)
+4.7. allow_address(group_id, ip_addr_pvar, port_pvar)
 
    Returns true if address and port given as values of pvar arguments
    belonging to a group given as group_id argument matches an IP subnet or
@@ -821,7 +822,7 @@ if (!allow_address("2", "$avp(dst_adr)", "$avp(dst_port)") {
 };
 ...
 
-4.8.  allow_source_address([group_id])
+4.8. allow_source_address([group_id])
 
    Equal to allow_address(group_id, "$si", "$sp"). If 'group_id' is
    missing, the function is equal to allow_address("1", "$si", "$sp").
@@ -837,7 +838,7 @@ if (!allow_source_address("1")) {
 };
 ...
 
-4.9.  allow_source_address_group()
+4.9. allow_source_address_group()
 
    Checks if source address/port is found in cached address or subnet
    table in any group. If yes, returns that group. If not returns -1. Port
@@ -854,7 +855,7 @@ if ($var(group) != -1) {
 };
 ...
 
-4.10.  allow_address_group(addr, port)
+4.10. allow_address_group(addr, port)
 
    Checks if address/port is found in cached address or subnet table in
    any group. If yes, returns that group. If not returns -1. Port value 0
@@ -872,19 +873,19 @@ if ($var(group) != -1) {
 };
 ...
 
-4.11.  allow_trusted([src_ip_pvar, proto_pvar])
+4.11. allow_trusted([src_ip_pvar, proto_pvar])
 
    Checks based either on request's source address and transport protocol
    or source address and transport protocol given in pvar arguments, and
    From URI of request if request can be trusted without authentication.
-   Returns 1 if a match is found as described in Section 1.5, “Trusted
-   Requests� and -1 otherwise. If a match is found and peer_tag_avp has
+   Returns 1 if a match is found as described in Section 1.5, "Trusted
+   Requests" and -1 otherwise. If a match is found and peer_tag_avp has
    been defined, adds a non-NULL tag column value of the matching peer to
    AVP peer_tag_avp.
 
    Source address and transport protocol given in pvar arguments must be
    in string format. Valid transport protocol values are (ignoring case)
-   "any", "udp, "tcp", "tls", and "sctp".
+   "any", "udp, "tcp", "tls", "ws", "wss" and "sctp".
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
@@ -908,7 +909,7 @@ if (allow_trusted("$si", "$proto")) {
    5.5. trusted_dump
    5.6. allow_uri
 
-5.1.  address_reload
+5.1. address_reload
 
    Causes permissions module to re-read the contents of address database
    table into cache memory. In cache memory the entries are for
@@ -917,35 +918,35 @@ if (allow_trusted("$si", "$proto")) {
 
    Parameters: none
 
-5.2.  address_dump
+5.2. address_dump
 
    Causes permissions module to dump contents of cache memory address
    table.
 
    Parameters: none
 
-5.3.  subnet_dump
+5.3. subnet_dump
 
    Causes permissions module to dump contents of cache memory subnet
    table.
 
    Parameters: none
 
-5.4.  trusted_reload
+5.4. trusted_reload
 
    Causes permissions module to re-read the contents of trusted table into
    cache memory.
 
    Parameters: none
 
-5.5.  trusted_dump
+5.5. trusted_dump
 
    Causes permissions module to dump contents of trusted table from cache
    memory.
 
    Parameters: none
 
-5.6.  allow_uri
+5.6. allow_uri
 
    Tests if (URI, Contact) pair is allowed according to allow/deny files.
    The files must already have been loaded by Kamailio.
@@ -966,7 +967,7 @@ if (allow_trusted("$si", "$proto")) {
    6.5. trustedReload
    6.6. trustedDump
 
-6.1.  addressReload
+6.1. addressReload
 
    Causes permissions module to re-read the contents of address database
    table into cache memory. In cache memory the entries are for
@@ -975,21 +976,21 @@ if (allow_trusted("$si", "$proto")) {
 
    Parameters: none
 
-6.2.  addressDump
+6.2. addressDump
 
    Causes permissions module to dump contents of cache memory address
    table. (Not the subnet table).
 
    Parameters: none
 
-6.3.  subnetDump
+6.3. subnetDump
 
    Causes permissions module to dump contents of cache memory subnet
    table.
 
    Parameters: none
 
-6.4.  testUri basename uri contact
+6.4. testUri basename uri contact
 
    Tests if (URI, Contact) pair is allowed according to allow/deny files.
    The files must already have been loaded by Kamailio.
@@ -1001,14 +1002,14 @@ if (allow_trusted("$si", "$proto")) {
      * URI - URI to be tested
      * Contact - Contact to be tested
 
-6.5.  trustedReload
+6.5. trustedReload
 
    Causes permissions module to re-read the contents of trusted table into
    cache memory.
 
    Parameters: none
 
-6.6.  trustedDump
+6.6. trustedDump
 
    Causes permissions module to dump contents of trusted table from cache
    memory.

+ 2 - 1
modules/permissions/doc/permissions_admin.xml

@@ -687,7 +687,8 @@ modparam("permissions", "peer_tag_avp", "$avp(i:707)")
 		<para>
 		Tag mode for allow_trusted(). 0 sets only the tag of the
 		first match. 1 adds the tags of all matches to the avp. In addition
-		the return value of allow_trusted() is the number of matches.
+		the return value of allow_trusted() is the number of matches. This
+		parameter is not used for address table matching functions.
 		</para>
 		<para>
 		<emphasis>

+ 20 - 0
modules/permissions/hash.c

@@ -486,6 +486,7 @@ int find_group_in_addr_hash_table(struct addr_list** table,
 {
 	struct addr_list *np;
 	str addr_str;
+	avp_value_t val;
 
 	addr_str.s = (char*)addr->u.addr;
 	addr_str.len = 4;
@@ -493,6 +494,15 @@ int find_group_in_addr_hash_table(struct addr_list** table,
 	for (np = table[perm_hash(addr_str)]; np != NULL; np = np->next) {
 		if (((np->port == 0) || (np->port == port))
 				&& ip_addr_cmp(&np->addr, addr)) {
+
+			if (tag_avp.n && np->tag.s) {
+				val.s = np->tag;
+				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
+					LM_ERR("setting of tag_avp failed\n");
+					return -1;
+				}
+			}
+
 			return np->grp;
 		}
 	}
@@ -710,6 +720,7 @@ int find_group_in_subnet_table(struct subnet* table,
 		ip_addr_t *addr, unsigned int port)
 {
 	unsigned int count, i;
+	avp_value_t val;
 
 	count = table[PERM_MAX_SUBNETS].grp;
 
@@ -717,7 +728,16 @@ int find_group_in_subnet_table(struct subnet* table,
 	while (i < count) {
 		if ( ((table[i].port == port) || (table[i].port == 0))
 			&& (ip_addr_match_net(addr, &table[i].subnet, table[i].mask)==0))
+		{
+			if (tag_avp.n && table[i].tag.s) {
+				val.s = table[i].tag;
+				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
+					LM_ERR("setting of tag_avp failed\n");
+					return -1;
+				}
+			}
 			return table[i].grp;
+		}
 		i++;
 	}
 

+ 70 - 15
modules/presence_dialoginfo/notify_body.c

@@ -32,6 +32,12 @@
  */
 
 #define MAX_INT_LEN 11 /* 2^32: 10 chars + 1 char sign */
+#define DEF_TRYING_NODE 1
+#define DEF_PROCEEDING_NODE 2
+#define DEF_EARLY_NODE 4
+#define DEF_CONFIRMED_NODE 8
+#define DEF_TERMINATED_NODE 16
+
 
 #include <string.h>
 #include <stdlib.h>
@@ -103,6 +109,9 @@ str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n)
 	xmlNodePtr terminated_node = NULL;
 	xmlNodePtr early_node = NULL;
 	xmlNodePtr confirmed_node = NULL;
+	xmlNodePtr proceed_node = NULL;
+	xmlNodePtr trying_node = NULL;
+
 
 	char *state = NULL;
 	xmlChar *dialog_id = NULL;
@@ -236,39 +245,61 @@ str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n)
 							LM_DBG("state element content = %s\n", state);
 							if (strcasecmp(state,"terminated") == 0)
 							{
+								LM_DBG("found terminated state\n" );
 								terminated_node = node;
 							} else if (strcasecmp(state,"confirmed") == 0 && node_id == i) {
 								/*  here we check if confirmed is terminated or not
 								 *  if it is not we are in the middle of the conversation
 								 */
-								if(check_relevant_state(dialog_id, xml_array, j) > 1)
+								if(check_relevant_state(dialog_id, xml_array, j) >= DEF_TERMINATED_NODE)
 								{
-									LM_DBG("confirmed state for dialog %s, but it was terminated\n", dialog_id );
+									LM_DBG("confirmed state for dialog %s, but it is not latest state\n", dialog_id );
 								}else{
-									LM_DBG("confirmed state for dialog %s, and it is not terminated\n", dialog_id );
+									LM_DBG("confirmed state for dialog %s and latest state for this dialog\n", dialog_id );
 									confirmed_node = node;
 								}
 
 
 							} else if (strcasecmp(state,"early") == 0 && node_id == i) {
-								if(check_relevant_state(dialog_id, xml_array, j)  > 0)
+								if(check_relevant_state(dialog_id, xml_array, j)  >= DEF_CONFIRMED_NODE)
 								{
-									LM_DBG("early state for dialog %s, but it was confirmed or terminated\n", dialog_id );
+									LM_DBG("early state for dialog %s, but it is not latest state\n", dialog_id );
 								}else{
-									LM_DBG("early state for dialog %s and it is still relevant\n", dialog_id );
+									LM_DBG("early state for dialog %s and latest state for this dialog\n", dialog_id );
 									early_node = node;
 								}
+							} else if (strcasecmp(state,"proceeding") == 0 && node_id == i) {
+								if(check_relevant_state(dialog_id, xml_array, j)  >= DEF_EARLY_NODE)
+								{
+									LM_DBG("proceeding state for dialog %s, but it is not latest state\n", dialog_id );
+								}else{
+									LM_DBG("proceeding state for dialog %s and latest state for this dialog\n", dialog_id );
+									proceed_node = node;
+								}
+							} else if (strcasecmp(state,"trying") == 0 && node_id == i) {
+								if(check_relevant_state(dialog_id, xml_array, j)  >= DEF_PROCEEDING_NODE)
+								{
+									LM_DBG("trying state for dialog %s, but it is not latest state\n", dialog_id );
+								}else{
+									LM_DBG("trying state for dialog %s and latest state for this dialog\n", dialog_id );
+									trying_node = node;
+								}
 							}
 							if(early_node != NULL) {
 								winner_dialog_node = early_node;
-							} else {
-								if(confirmed_node != NULL)
-								{
+							} else if(confirmed_node != NULL) {
 									winner_dialog_node = confirmed_node;
-								}else {
+							} else if(proceed_node != NULL) {
+									winner_dialog_node = proceed_node;
+							} else if(trying_node != NULL) {
+									winner_dialog_node = trying_node;
+							} else if(terminated_node != NULL) {
 									winner_dialog_node = terminated_node;
-								}
+							} else {
+								/* assume a failure somewhere and all above nodes are NULL */
+								winner_dialog_node = node;
 							}
+							/*
 							if(winner_dialog_node == NULL) {
 								priority = get_dialog_state_priority(state);
 								if (priority > winner_priority) {
@@ -277,6 +308,7 @@ str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n)
 									winner_dialog_node = node;
 								}
 							}
+							*/
 							xmlFree(state);
 						}
 					}
@@ -336,7 +368,7 @@ error:
 	return NULL;
 }
 
-
+/*
 int get_dialog_state_priority(char *state) {
 	if (strcasecmp(state,"terminated") == 0)
 		return 0;
@@ -351,8 +383,9 @@ int get_dialog_state_priority(char *state) {
 
 	return 0;
 }
+*/
 
-/* returns 2 -> terminated, 1 -> confirmed, 3 -> both */
+/* returns 16 -> terminated, 8 -> confirmed, 4 -> early */
 int check_relevant_state (xmlChar * dialog_id, xmlDocPtr * xml_array, int total_nodes)
 {
 	int result = 0;
@@ -391,7 +424,7 @@ int check_relevant_state (xmlChar * dialog_id, xmlDocPtr * xml_array, int total_
 							{
 								LM_DBG ("Found terminated in dialog %s\n",
 										dialog_id);
-								result += 2;
+								result += DEF_TERMINATED_NODE;
 							}
 							/* check if state is confirmed for this dialog. */
 							if ((strcasecmp (state, "confirmed") == 0)
@@ -399,8 +432,30 @@ int check_relevant_state (xmlChar * dialog_id, xmlDocPtr * xml_array, int total_
 									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
 							{
 								LM_DBG ("Found confirmed in dialog %s\n", dialog_id);
-								result += 1;
+								result += DEF_CONFIRMED_NODE;
 							}
+							if ((strcasecmp (state, "early") == 0)
+									&& (node_id == i) && (node_id >= 0)
+									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
+							{
+								LM_DBG ("Found early in dialog %s\n", dialog_id);
+								result += DEF_EARLY_NODE;
+							}
+							if ((strcasecmp (state, "proceeding") == 0)
+									&& (node_id == i) && (node_id >= 0)
+									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
+							{
+								LM_DBG ("Found proceeding in dialog %s\n", dialog_id);
+								result += DEF_PROCEEDING_NODE;
+							}
+							if ((strcasecmp (state, "trying") == 0)
+									&& (node_id == i) && (node_id >= 0)
+									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
+							{
+								LM_DBG ("Found trying in dialog %s\n", dialog_id);
+								result += DEF_TRYING_NODE;
+							}
+
 
 							xmlFree (state);
 						}

+ 2 - 1
modules/tls/tls_cfg.c

@@ -2,6 +2,7 @@
  * TLS module
  *
  * Copyright (C) 2010 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -76,7 +77,7 @@ struct cfg_group_tls default_tls_cfg = {
 	0 /* send_close_notify (off by default)*/
 };
 
-void* tls_cfg = &default_tls_cfg;
+volatile void* tls_cfg = &default_tls_cfg;
 
 
 /* if *to<0 to=default_val, else if to>max_val to=max_val */

+ 2 - 1
modules/tls/tls_cfg.h

@@ -2,6 +2,7 @@
  * TLS module
  * 
  * Copyright (C) 2010 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -101,7 +102,7 @@ struct cfg_group_tls {
 
 
 extern struct cfg_group_tls default_tls_cfg;
-extern void* tls_cfg;
+extern volatile void* tls_cfg;
 extern cfg_def_t tls_cfg_def[];
 
 

+ 2 - 1
modules/tls/tls_domain.c

@@ -2,6 +2,7 @@
  * TLS module
  *
  * Copyright (C) 2005,2006 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -23,7 +24,6 @@
  * Module: @ref tls
  */
 
-
 #include <stdlib.h>
 #include <openssl/ssl.h>
 #include <openssl/opensslv.h>
@@ -119,6 +119,7 @@ void tls_free_cfg(tls_domains_cfg_t* cfg)
 	}
 	if (cfg->srv_default) tls_free_domain(cfg->srv_default);
 	if (cfg->cli_default) tls_free_domain(cfg->cli_default);
+	shm_free(cfg);
 }
 
 

+ 2 - 1
modules/tls/tls_domain.h

@@ -2,6 +2,7 @@
  * TLS module
  *
  * Copyright (C) 2005,2006 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -99,7 +100,7 @@ typedef struct tls_domains_cfg {
 	tls_domain_t* srv_list;    /**< Server domain list */
 	tls_domain_t* cli_list;    /**< Client domain list */
 	struct tls_domains_cfg* next; /**< Next element in the garbage list */
-	int ref_count;             /**< How many connections use this configuration */
+	volatile int ref_count;             /**< How many connections use this configuration */
 } tls_domains_cfg_t;
 
 

+ 2 - 1
modules/tls/tls_mod.c

@@ -2,6 +2,7 @@
  * TLS module
  *
  * Copyright (C) 2007 iptelorg GmbH 
+ * Copyright (C) Motorola Solutions, Inc.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -278,7 +279,7 @@ static int mod_init(void)
 	}
 	/* declare configuration */
 	if (cfg_declare("tls", tls_cfg_def, &default_tls_cfg,
-							cfg_sizeof(tls), &tls_cfg)) {
+							cfg_sizeof(tls), (void **)&tls_cfg)) {
 		ERR("failed to register the configuration\n");
 		return -1;
 	}

+ 9 - 1
modules/tls/tls_rpc.c

@@ -2,6 +2,7 @@
  * TLS module - management interface
  *
  * Copyright (C) 2005 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  * This file is part of sip-router, a free SIP server.
  *
@@ -56,10 +57,11 @@ static void tls_reload(rpc_t* rpc, void* ctx)
 		return;
 	}
 
-	     /* Try to delete old configurations first */
+	/* Try to delete old configurations first */
 	collect_garbage();
 
 	cfg = tls_load_config(&tls_domains_cfg_file);
+
 	if (!cfg) {
 		rpc->fault(ctx, 500, "Error while loading TLS configuration file"
 							" (consult server log)");
@@ -78,8 +80,14 @@ static void tls_reload(rpc_t* rpc, void* ctx)
 	}
 
 	DBG("TLS configuration successfuly loaded");
+
+	lock_get(tls_domains_cfg_lock);
+
 	cfg->next = (*tls_domains_cfg);
 	*tls_domains_cfg = cfg;
+
+	lock_release(tls_domains_cfg_lock);
+
 	return;
 
  error:

+ 5 - 6
modules/tls/tls_server.c

@@ -2,6 +2,7 @@
  * TLS module - main server part
  *
  * Copyright (C) 2005-2010 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  * This file is part of SIP-router, a free SIP server.
  *
@@ -148,13 +149,10 @@ static int tls_complete_init(struct tcp_connection* c)
 		goto error2;
 	}
 	     /* Get current TLS configuration and increase reference
-	      * count immediately. There is no need to lock the structure
-	      * here, because it does not get deleted immediately. When
-	      * SER reloads TLS configuration it will put the old configuration
-	      * on a garbage queue and delete it later, so we know here that
-	      * the pointer we get from *tls_domains_cfg will be valid for a while,
-		  * at least by the time this function finishes
+	      * count immediately.
 	      */
+
+	lock_get(tls_domains_cfg_lock);
 	cfg = *tls_domains_cfg;
 
 	     /* Increment the reference count in the configuration structure, this
@@ -162,6 +160,7 @@ static int tls_complete_init(struct tcp_connection* c)
 	      * not get deleted if there are still connection referencing its SSL_CTX
 	      */
 	cfg->ref_count++;
+	lock_release(tls_domains_cfg_lock);
 
 	if (c->flags & F_CONN_PASSIVE) {
 		state=S_TLS_ACCEPTING;

+ 9 - 5
modules/tls/tls_util.c

@@ -2,6 +2,7 @@
  * TLS module
  *
  * Copyright (C) 2005 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,6 +17,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+
 #define _GNU_SOURCE 1 /* Needed for strndup */
 
 #include <string.h>
@@ -66,7 +68,7 @@ int shm_asciiz_dup(char** dest, char* val)
  */
 void collect_garbage(void)
 {
-	tls_domains_cfg_t* prev, *cur;
+	tls_domains_cfg_t *prev, *cur, *next;
 
 	     /* Make sure we do not run two garbage collectors
 	      * at the same time
@@ -80,14 +82,16 @@ void collect_garbage(void)
 	cur = (*tls_domains_cfg)->next;
 
 	while(cur) {
+		next = cur->next;
 		if (cur->ref_count == 0) {
-			     /* Not referenced by any existing connection */
+			/* Not referenced by any existing connection */
 			prev->next = cur->next;
 			tls_free_cfg(cur);
+		} else {
+			/* Only update prev if we didn't remove cur */
+			prev = cur;
 		}
-
-		prev = cur;
-		cur = cur->next;
+		cur = next;
 	}
 
 	lock_release(tls_domains_cfg_lock);

+ 5 - 2
modules/websocket/ws_frame.c

@@ -141,6 +141,7 @@ static int encode_and_send_ws_frame(ws_frame_t *frame, conn_close_t conn_close)
 	struct dest_info dst;
 	union sockaddr_union *from = NULL;
 	union sockaddr_union local_addr;
+	int sub_proto;
 
 	LM_DBG("encoding WebSocket frame\n");
 
@@ -166,6 +167,8 @@ static int encode_and_send_ws_frame(ws_frame_t *frame, conn_close_t conn_close)
 		return -1;
 	}
 
+	sub_proto = frame->wsc->sub_protocol;
+
 	switch(frame->opcode)
 	{
 	case OPCODE_TEXT_FRAME:
@@ -299,9 +302,9 @@ static int encode_and_send_ws_frame(ws_frame_t *frame, conn_close_t conn_close)
 		LM_ERR("sending WebSocket frame\n");
 		pkg_free(send_buf);
 		update_stat(ws_failed_connections, 1);
-		if (frame->wsc->sub_protocol == SUB_PROTOCOL_SIP)
+		if (sub_proto == SUB_PROTOCOL_SIP)
 			update_stat(ws_sip_failed_connections, 1);
-		else if (frame->wsc->sub_protocol == SUB_PROTOCOL_MSRP)
+		else if (sub_proto == SUB_PROTOCOL_MSRP)
 			update_stat(ws_msrp_failed_connections, 1);
 		if (wsconn_rm(frame->wsc, WSCONN_EVENTROUTE_YES) < 0)
 			LM_ERR("removing WebSocket connection\n");