summaryrefslogtreecommitdiff
path: root/channels/chan_gtalk.c
diff options
context:
space:
mode:
authorKinsey Moore <kmoore@digium.com>2011-11-23 17:16:33 +0000
committerKinsey Moore <kmoore@digium.com>2011-11-23 17:16:33 +0000
commite6ca7680812d1ecbf45419ca92bcadacbd6fa47f (patch)
tree04c71e8b003cc527bf960a9b0e8343ee84b0c02b /channels/chan_gtalk.c
parent76394a727f5b18fbb0506ddcecfa6494d7cff31c (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.c25
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);