diff options
author | Kinsey Moore <kmoore@digium.com> | 2011-11-23 17:16:33 +0000 |
---|---|---|
committer | Kinsey Moore <kmoore@digium.com> | 2011-11-23 17:16:33 +0000 |
commit | e6ca7680812d1ecbf45419ca92bcadacbd6fa47f (patch) | |
tree | 04c71e8b003cc527bf960a9b0e8343ee84b0c02b /channels/chan_gtalk.c | |
parent | 76394a727f5b18fbb0506ddcecfa6494d7cff31c (diff) |
Fix res_jabber resource leaks
This should fix almost all resource leaks in res_jabber that involve
ASTOBJ_CONTAINER_FIND and resolves an ambiguous situation where
ast_aji_get_client would sometimes bump an object's refcount and sometimes not.
Review: https://reviewboard.asterisk.org/r/1553
........
Merged revisions 346086 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 346087 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@346088 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/chan_gtalk.c')
-rw-r--r-- | channels/chan_gtalk.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c index cf58d6c4b..855c89ba2 100644 --- a/channels/chan_gtalk.c +++ b/channels/chan_gtalk.c @@ -248,9 +248,17 @@ static struct gtalk_container gtalk_list; static void gtalk_member_destroy(struct gtalk *obj) { obj->cap = ast_format_cap_destroy(obj->cap); + if (obj->connection) { + ASTOBJ_UNREF(obj->connection, ast_aji_client_destroy); + } + if (obj->buddy) { + ASTOBJ_UNREF(obj->buddy, ast_aji_buddy_destroy); + } ast_free(obj); } +/* XXX This could be a source of reference leaks given that the CONTAINER_FIND + * macros bump the refcount while the traversal does not. */ static struct gtalk *find_gtalk(char *name, char *connection) { struct gtalk *gtalk = NULL; @@ -995,7 +1003,7 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const { struct gtalk_pvt *tmp = NULL; struct aji_resource *resources = NULL; - struct aji_buddy *buddy; + struct aji_buddy *buddy = NULL; char idroster[200]; char *data, *exten = NULL; struct ast_sockaddr bindaddr_tmp; @@ -1023,8 +1031,14 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const snprintf(idroster, sizeof(idroster), "%s", them); } else { ast_log(LOG_ERROR, "no gtalk capable clients to talk to.\n"); + if (buddy) { + ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); + } return NULL; } + if (buddy) { + ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); + } } if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { return NULL; @@ -1309,6 +1323,9 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak) if (!strcasecmp(client->name, "guest")){ /* the guest account is not tied to any configured XMPP client, let's set it now */ + if (client->connection) { + ASTOBJ_UNREF(client->connection, ast_aji_client_destroy); + } client->connection = ast_aji_get_client(from); if (!client->connection) { ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from); @@ -1909,6 +1926,9 @@ static struct ast_channel *gtalk_request(const char *type, struct ast_format_cap if (!strcasecmp(client->name, "guest")){ /* the guest account is not tied to any configured XMPP client, let's set it now */ + if (client->connection) { + ASTOBJ_UNREF(client->connection, ast_aji_client_destroy); + } client->connection = ast_aji_get_client(sender); if (!client->connection) { ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender); @@ -2239,6 +2259,9 @@ static int gtalk_load_config(void) ASTOBJ_CONTAINER_TRAVERSE(clients, 1, { ASTOBJ_WRLOCK(iterator); ASTOBJ_WRLOCK(member); + if (member->connection) { + ASTOBJ_UNREF(member->connection, ast_aji_client_destroy); + } member->connection = NULL; iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, GOOGLE_NS, IKS_RULE_DONE); iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, GOOGLE_JINGLE_NS, IKS_RULE_DONE); |