aboutsummaryrefslogtreecommitdiffstats
path: root/res
diff options
context:
space:
mode:
authorphsultan <phsultan@f38db490-d61c-443f-a65b-d21fe96a405b>2007-08-16 09:37:10 +0000
committerphsultan <phsultan@f38db490-d61c-443f-a65b-d21fe96a405b>2007-08-16 09:37:10 +0000
commitb50b8d670fc78088726e453558a4c659e168cbd6 (patch)
tree1f2de4d3b3836c603f3cfa07d332f1cd0087d240 /res
parent89f734ab31dd6dd8f0ecd37a35a94be5c6c881be (diff)
A fix for two critical problems detected while working with Daniel
McKeehan in issue #10184. Upon priority change, the resource list is not NULL terminated when moving an item to the end of the list. This makes Asterisk endlessy loop whenever it needs to read the list. Jids with different resource and priority values, like in Gmail's and GoogleTalk's jabber clients put that problem in evidence. Upon reception of a 'from' attribute with an empty resource string, Asterisk crashes when trying to access the found->cap pointer if the resource list for the given buddy is not empty. This situation is perfectly valid and must be handled. The Gizmoproject's jabber client put that problem in evidence. Also added a few comments in the code as well as a handle for the capabilities from Gmail's jabber client, which are stored in a caps:c tag rather than the usual c tag. Closes issue #10184. git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@79665 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'res')
-rw-r--r--res/res_jabber.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/res/res_jabber.c b/res/res_jabber.c
index 6e7344591..722a8bbb1 100644
--- a/res/res_jabber.c
+++ b/res/res_jabber.c
@@ -1209,29 +1209,42 @@ static void aji_handle_presence(struct aji_client *client, ikspak *pak)
found = NULL;
break;
}
+ /* resource list is sorted by descending priority */
if (tmp->priority != priority) {
found->priority = priority;
if (!last && !found->next)
+ /* resource was found to be unique,
+ leave loop */
break;
+ /* search for resource in our list
+ and take it out for the moment */
if (last)
last->next = found->next;
else
buddy->resources = found->next;
+
last = NULL;
tmp = buddy->resources;
if (!buddy->resources)
buddy->resources = found;
+ /* priority processing */
while (tmp) {
+ /* insert resource back according to
+ its priority value */
if (found->priority > tmp->priority) {
if (last)
+ /* insert within list */
last->next = found;
found->next = tmp;
if (!last)
+ /* insert on top */
buddy->resources = found;
break;
}
if (!tmp->next) {
+ /* insert at the end of the list */
tmp->next = found;
+ found->next = NULL;
break;
}
last = tmp;
@@ -1244,6 +1257,7 @@ static void aji_handle_presence(struct aji_client *client, ikspak *pak)
tmp = tmp->next;
}
+ /* resource not found in our list, create it */
if (!found && status != 6) {
found = (struct aji_resource *) malloc(sizeof(struct aji_resource));
memset(found, 0, sizeof(struct aji_resource));
@@ -1278,12 +1292,25 @@ static void aji_handle_presence(struct aji_client *client, ikspak *pak)
if (!tmp)
buddy->resources = found;
}
+
+ /* if 'from' attribute does not contain 'resource' string
+ point to the top of our resource list */
+ if (!found && !pak->from->resource && buddy->resources) {
+ found = buddy->resources;
+ }
+
ASTOBJ_UNLOCK(buddy);
ASTOBJ_UNREF(buddy, aji_buddy_destroy);
node = iks_find_attrib(iks_find(pak->x, "c"), "node");
ver = iks_find_attrib(iks_find(pak->x, "c"), "ver");
+ /* handle gmail client's special caps:c tag */
+ if (!node && !ver) {
+ node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node");
+ ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver");
+ }
+
if(status !=6 && !found->cap) {
found->cap = aji_find_version(node, ver, pak);
if(gtalk_yuck(pak->x)) /* gtalk should do discover */