Index: channels/chan_jingle.c =================================================================== --- channels/chan_jingle.c (revision 114698) +++ channels/chan_jingle.c (working copy) @@ -64,7 +64,7 @@ #include "asterisk/stringfields.h" #include "asterisk/utils.h" #include "asterisk/causes.h" -#include "asterisk/astobj.h" +#include "asterisk/astobj2.h" #include "asterisk/abstract_jb.h" #include "asterisk/jabber.h" #include "asterisk/jingle.h" @@ -135,7 +135,6 @@ }; struct jingle { - ASTOBJ_COMPONENTS(struct jingle); struct aji_client *connection; struct aji_buddy *buddy; struct jingle_pvt *p; @@ -154,10 +153,18 @@ char parkinglot[AST_MAX_CONTEXT]; /*!< Parkinglot */ }; -struct jingle_container { - ASTOBJ_CONTAINER_COMPONENTS(struct jingle); -}; +static int jingle_cmp_fn(void *obj, void *arg, int flags) +{ + struct jingle *j1,*j2 = obj,arg; + return strcasecmp(j1->name,j2->name) ? CMP_MATCH : 0; +} +static int jingle_cmp_user_fn(void *obj, void *arg, int flags) +{ + struct jingle *j1,*j2 = obj,arg; + return strcasecmp(j1->name,j2) ? CMP_MATCH : 0; +} + static const char desc[] = "Jingle Channel"; static const char type[] = "Jingle"; @@ -231,7 +238,7 @@ static char externip[16]; -static struct jingle_container jingle_list; +static struct ao2_container *jingle_list; static void jingle_member_destroy(struct jingle *obj) { @@ -240,27 +247,34 @@ static struct jingle *find_jingle(char *name, char *connection) { - struct jingle *jingle = NULL; + struct jingle *j, *jingle, tmp_jingle; + struct ao2_iterator iter; - jingle = ASTOBJ_CONTAINER_FIND(&jingle_list, name); + ast_copy_string(tmp_jingle.name, name, sizeof(tmp_jingle.name)); + + jingle = ao2_find(jingle_list, &tmp_jingle, OBJ_POINTER); + if (!jingle && strchr(name, '@')) - jingle = ASTOBJ_CONTAINER_FIND_FULL(&jingle_list, name, user,,, strcasecmp); + jingle = ao2_callback(jingle_list, OBJ_POINTER, jingle_cmp_fn, name); if (!jingle) { /* guest call */ - ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, { - ASTOBJ_RDLOCK(iterator); - if (!strcasecmp(iterator->name, "guest")) { - if (!strcasecmp(iterator->connection->jid->partial, connection)) { - jingle = iterator; - } else if (!strcasecmp(iterator->connection->name, connection)) { - jingle = iterator; + iter = ao2_iterator_init(jingle_list, 0); + + while(j = ao2_iterator_next(&iter)) { + ao2_lock(j); + if (!strcasecmp(j->name, "guest")) { + if (!strcasecmp(j->connection->jid->partial, connection)) { + jingle = j; + } else if (!strcasecmp(j->connection->name, connection)) { + jingle = j; } } - ASTOBJ_UNLOCK(iterator); + ao2_ref(j,-1); + ao2_unlock(j); if (jingle) break; - }); + } } return jingle; @@ -748,7 +762,7 @@ ast_debug(1, "The client is %s for alloc\n", client->name); if (!sid && !strchr(from, '/')) { /* I started call! */ if (!strcasecmp(client->name, "guest")) { - buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, from); + buddy = ao2_find(client->connection->buddies, from, OBJ_POINTER); if (buddy) resources = buddy->resources; } else if (client->buddy) @@ -1442,11 +1456,11 @@ ast_log(LOG_WARNING, "Could not find recipient.\n"); return NULL; } - ASTOBJ_WRLOCK(client); + ao2_lock(client); p = jingle_alloc(client, to, NULL); if (p) chan = jingle_new(client, p, AST_STATE_DOWN, to); - ASTOBJ_UNLOCK(client); + ao2_unlock(client); return chan; } @@ -1456,7 +1470,9 @@ { #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" struct jingle_pvt *p; + struct jingle *j; struct ast_channel *chan; + struct ao2_iterator i; int numchans = 0; char them[AJI_MAX_JIDLEN]; char *jid = NULL; @@ -1476,11 +1492,12 @@ if (a->argc != 3) return CLI_SHOWUSAGE; + i = ao2_iterator_init(jingle_list,0); ast_mutex_lock(&jinglelock); ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write"); - ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, { - ASTOBJ_WRLOCK(iterator); - p = iterator->p; + while( (j = ao2_iterator_next(&i)) ) { + ao2_lock(j); + p = j->p; while(p) { chan = p->owner; ast_copy_string(them, p->them, sizeof(them)); @@ -1505,8 +1522,9 @@ numchans ++; p = p->next; } - ASTOBJ_UNLOCK(iterator); - }); + ao2_unlock(j); + ao2_ref(j, -1); + }; ast_mutex_unlock(&jinglelock); @@ -1534,7 +1552,7 @@ static int jingle_parser(void *data, ikspak *pak) { - struct jingle *client = ASTOBJ_REF((struct jingle *) data); + struct jingle *client = ao2_ref((struct jingle *) data, 1); ast_log(LOG_NOTICE, "Filter matched\n"); if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) { @@ -1553,7 +1571,7 @@ } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) { jingle_hangup_farend(client, pak); } - ASTOBJ_UNREF(client, jingle_member_destroy); + ao2_ref(client, -1); return IKS_FILTER_EAT; } /* Not using this anymore probably take out soon @@ -1656,7 +1674,7 @@ var = var->next; } if (member->connection && member->user) - member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user); + member->buddy = ao2_find(member->connection->buddies, member->user, OBJ_POINTER); else { ast_log(LOG_ERROR, "No Connection or Username!\n"); } @@ -1674,7 +1692,6 @@ struct hostent *hp; struct ast_hostent ahp; struct ast_codec_pref prefs; - struct aji_client_container *clients; struct jingle_candidate *global_candidates = NULL; struct ast_flags config_flags = { 0 }; @@ -1723,9 +1740,8 @@ while (cat) { if (strcasecmp(cat, "general")) { var = ast_variable_browse(cfg, cat); - member = ast_calloc(1, sizeof(*member)); - ASTOBJ_INIT(member); - ASTOBJ_WRLOCK(member); + ao2_t_alloc(sizeof(struct jingle), jingle_destructor, "allocate jingle struct"); + ao2_lock(member); if (!strcasecmp(cat, "guest")) { ast_copy_string(member->name, "guest", sizeof(member->name)); ast_copy_string(member->user, "guest", sizeof(member->user)); @@ -1757,28 +1773,31 @@ */ var = var->next; } - ASTOBJ_UNLOCK(member); - clients = ast_aji_get_clients(); + ao2_unlock(member); + if (clients) { - ASTOBJ_CONTAINER_TRAVERSE(clients, 1, { - ASTOBJ_WRLOCK(iterator); - ASTOBJ_WRLOCK(member); - member->connection = iterator; - iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_NS, IKS_RULE_DONE); - iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_DTMF_NS, IKS_RULE_DONE); - ASTOBJ_UNLOCK(member); - ASTOBJ_CONTAINER_LINK(&jingle_list, member); - ASTOBJ_UNLOCK(iterator); - }); + struct ao2_iterator i; + struct jingle *o; + i = ao2_iterator_init(clients, 0); + while( (o = ao2_iterator_next(&i)) ){ + ao2_lock(member); + ao2_lock(o); + member->connection = o; + iks_filter_add_rule(o->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_NS, IKS_RULE_DONE); + iks_filter_add_rule(o->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_DTMF_NS, IKS_RULE_DONE); + ao2_unlock(member); + ao2_t_link(jingle_list, member, "add jingle member"); + ao2_unlock(o); + } } else { - ASTOBJ_UNLOCK(member); - ASTOBJ_UNREF(member, jingle_member_destroy); + ao2_unlock(member); + ao2_ref(member, -1); } } else { - ASTOBJ_UNLOCK(member); + ao2_unlock(member); if (jingle_create_member(cat, var, allowguest, prefs, context, member)) - ASTOBJ_CONTAINER_LINK(&jingle_list, member); - ASTOBJ_UNREF(member, jingle_member_destroy); + ao2_t_link(jingle_list, member, "add jingle member"); + ao2_ref(member, -1); } } cat = ast_category_browse(cfg, cat); @@ -1790,6 +1809,8 @@ /*! \brief Load module into PBX, register channel */ static int load_module(void) { + jingles = ao2_container_alloc(MAX_JINGLE_BUCKETS,jingle_hash_cb,jingle_cmp_cb); + char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0); free(jabber_loaded); if (!jabber_loaded) { @@ -1797,7 +1818,6 @@ return AST_MODULE_LOAD_DECLINE; } - ASTOBJ_CONTAINER_INIT(&jingle_list); if (!jingle_load_config()) { ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG); return AST_MODULE_LOAD_DECLINE; @@ -1843,24 +1863,36 @@ if (!ast_mutex_lock(&jinglelock)) { /* Hangup all interfaces if they have an owner */ - ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, { - ASTOBJ_WRLOCK(iterator); - privates = iterator->p; + struct ao2_iterator i; + struct jingle *o; + i = ao2_iterator_init(jingle_list, 0); + while( ( o = ao2_iterator_next(&i) ) ) { + ao2_lock(o); + privates = o->p; while(privates) { if (privates->owner) ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD); privates = privates->next; } - iterator->p = NULL; - ASTOBJ_UNLOCK(iterator); - }); + o->p = NULL; + ao2_unlock(o); + ao2_ref(o,-1); + } ast_mutex_unlock(&jinglelock); } else { ast_log(LOG_WARNING, "Unable to lock the monitor\n"); return -1; } - ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy); - ASTOBJ_CONTAINER_DESTROY(&jingle_list); + + struct ao2_iterator iter; + + iter = ao2_iterator_init(jingle_list, 0); + + while( (o = ao2_iterator_next(&iter)) ) { + ao2_unlink(jingle_list, o, "remove jingle member"); + ao2_ref(o, -1); + } + return 0; } Index: channels/chan_gtalk.c =================================================================== --- channels/chan_gtalk.c (revision 114698) +++ channels/chan_gtalk.c (working copy) @@ -45,14 +45,16 @@ #include #include "asterisk/lock.h" -#include "asterisk/channel.h" #include "asterisk/config.h" #include "asterisk/module.h" #include "asterisk/pbx.h" -#include "asterisk/sched.h" -#include "asterisk/io.h" +//#include "asterisk/sched.h" in pbx.h +//#include "asterisk/io.h" in rtp.h +//#include "asterisk/channel.h" in rtp.h +//#include "asterisk/utils.h" in module.h +//#include "asterisk/abstract_jb.h" in channel.h #include "asterisk/rtp.h" -#include "asterisk/acl.h" +#include "asterisk/acl.h" //incs network.h and io.h #include "asterisk/callerid.h" #include "asterisk/file.h" #include "asterisk/cli.h" @@ -60,10 +62,9 @@ #include "asterisk/musiconhold.h" #include "asterisk/manager.h" #include "asterisk/stringfields.h" -#include "asterisk/utils.h" #include "asterisk/causes.h" #include "asterisk/astobj.h" -#include "asterisk/abstract_jb.h" +#include "asterisk/astobj2.h" #include "asterisk/jabber.h" #define GOOGLE_CONFIG "gtalk.conf" @@ -134,7 +135,6 @@ }; struct gtalk { - ASTOBJ_COMPONENTS(struct gtalk); struct aji_client *connection; struct aji_buddy *buddy; struct gtalk_pvt *p; @@ -153,10 +153,6 @@ char musicclass[MAX_MUSICCLASS]; /*!< Music on Hold class */ }; -struct gtalk_container { - ASTOBJ_CONTAINER_COMPONENTS(struct gtalk); -}; - static const char desc[] = "Gtalk Channel"; static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263; @@ -230,7 +226,7 @@ static char externip[16]; -static struct gtalk_container gtalk_list; +static struct ao2_container *gtalk_list; static void gtalk_member_destroy(struct gtalk *obj) { @@ -239,7 +235,9 @@ static struct gtalk *find_gtalk(char *name, char *connection) { - struct gtalk *gtalk = NULL; + struct gtalk *gtalk, *g = NULL; + struct gtalk tmp_gtalk; + struct ao2_iterator i; char *domain = NULL , *s = NULL; if (strchr(connection, '@')) { @@ -247,27 +245,33 @@ domain = strsep(&s, "@"); ast_verbose("OOOOH domain = %s\n", domain); } - gtalk = ASTOBJ_CONTAINER_FIND(>alk_list, name); + + ast_copy_string(tmp_gtalk.name,name,sizeof(tmp_gtalk.name)); + + gtalk = ao2_find(gtalk_list, &tmp_gtalk, OBJ_POINTER); + if (!gtalk && strchr(name, '@')) - gtalk = ASTOBJ_CONTAINER_FIND_FULL(>alk_list, name, user,,, strcasecmp); + gtalk = ao2_callback(gtalk_list, OBJ_POINTER, gtalk_cmp_fn, name); if (!gtalk) { /* guest call */ - ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { - ASTOBJ_RDLOCK(iterator); - if (!strcasecmp(iterator->name, "guest")) { - if (!strcasecmp(iterator->connection->jid->partial, connection)) { - gtalk = iterator; - } else if (!strcasecmp(iterator->connection->name, connection)) { - gtalk = iterator; - } else if (iterator->connection->component && !strcasecmp(iterator->connection->user,domain)) { - gtalk = iterator; + i = ao2_iterator_init(gtalk_list, 0); + while(g = ao2_t_iterator_next(&i, "iter through gtalk_list")) { + ao2_lock(g); + if (!strcasecmp(g->name, "guest")) { + if (!strcasecmp(g->connection->jid->partial, connection)) { + gtalk = g; + } else if (!strcasecmp(g->connection->name, connection)) { + gtalk = g; + } else if (g->connection->component && !strcasecmp(g->connection->user, domain)) { + gtalk = g; } } - ASTOBJ_UNLOCK(iterator); + ao2_t_ref(g, -1, "throw iter_next"); + ao2_unlock(g); if (gtalk) break; - }); + } } return gtalk; @@ -892,7 +896,7 @@ ast_debug(1, "The client is %s for alloc\n", client->name); if (!sid && !strchr(them, '/')) { /* I started call! */ if (!strcasecmp(client->name, "guest")) { - buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, them); + buddy = ao2_find(client->connection->buddies, them, OBJ_POINTER); if (buddy) resources = buddy->resources; } else if (client->buddy) @@ -1607,12 +1611,12 @@ ast_log(LOG_WARNING, "Could not find recipient.\n"); return NULL; } - ASTOBJ_WRLOCK(client); + ao2_lock(client); p = gtalk_alloc(client, strchr(sender, '@') ? sender : client->connection->jid->full, strchr(to, '@') ? to : client->user, NULL); if (p) chan = gtalk_new(client, p, AST_STATE_DOWN, to); - ASTOBJ_UNLOCK(client); + ao2_unlock(client); return chan; } @@ -1622,6 +1626,7 @@ #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" struct gtalk_pvt *p; struct ast_channel *chan; + struct ao2_iterator i; int numchans = 0; char them[AJI_MAX_JIDLEN]; char *jid = NULL; @@ -1642,10 +1647,11 @@ return CLI_SHOWUSAGE; ast_mutex_lock(>alklock); + i = ao2_iterator_init(gtalk_list, 0); ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write"); - ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { - ASTOBJ_WRLOCK(iterator); - p = iterator->p; + while( ( g = ao2_t_iterator_next(&i, "Iter gtalk item for gtalk show channels")) ){ + ao2_lock(g); + p = g->p; while(p) { chan = p->owner; ast_copy_string(them, p->them, sizeof(them)); @@ -1670,8 +1676,9 @@ numchans ++; p = p->next; } - ASTOBJ_UNLOCK(iterator); - }); + ao2_unlock(g); + ao2_t_ref(g, -1, "Toss ptr gtalk iterator_next gtalk show channel"); + }; ast_mutex_unlock(>alklock); @@ -1700,7 +1707,7 @@ static int gtalk_parser(void *data, ikspak *pak) { - struct gtalk *client = ASTOBJ_REF((struct gtalk *) data); + struct gtalk *client = ao2_t_ref((struct gtalk *) data,1, "add ref for pref parsing"); if (iks_find_with_attrib(pak->x, "session", "type", "initiate")) { /* New call */ @@ -1720,7 +1727,7 @@ } else if (iks_find_with_attrib(pak->x, "session", "type", "reject")) { gtalk_hangup_farend(client, pak); } - ASTOBJ_UNREF(client, gtalk_member_destroy); + ao2_t_ref(client, -1, "toss ref for pref passing"); return IKS_FILTER_EAT; } @@ -1825,7 +1832,7 @@ var = var->next; } if (member->connection && member->user) - member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user); + member->buddy = ao2_find(member->connection->buddies, member->user, OBJ_POINTER); else { ast_log(LOG_ERROR, "No Connection or Username!\n"); } @@ -1894,8 +1901,8 @@ if (strcasecmp(cat, "general")) { var = ast_variable_browse(cfg, cat); member = ast_calloc(1, sizeof(*member)); - ASTOBJ_INIT(member); - ASTOBJ_WRLOCK(member); + ao2_t_ref(member, 1, "Add ref for member"); + ao2_lock(member); if (!strcasecmp(cat, "guest")) { ast_copy_string(member->name, "guest", sizeof(member->name)); ast_copy_string(member->user, "guest", sizeof(member->user)); @@ -1928,28 +1935,30 @@ */ var = var->next; } - ASTOBJ_UNLOCK(member); + ao2_unlock(member); clients = ast_aji_get_clients(); if (clients) { - ASTOBJ_CONTAINER_TRAVERSE(clients, 1, { - ASTOBJ_WRLOCK(iterator); - ASTOBJ_WRLOCK(member); - member->connection = iterator; - iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://www.google.com/session", IKS_RULE_DONE); - iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://jabber.org/protocol/gtalk", IKS_RULE_DONE); - ASTOBJ_UNLOCK(member); - ASTOBJ_CONTAINER_LINK(>alk_list, member); - ASTOBJ_UNLOCK(iterator); + struct ao2_iterator i; + i = ao2_iterator_init(clients, 0); + while((c = ao2_t_iterator_next(&i, "Iter client list"))) { + ao2_lock(c); + ao2_lock(member); + member->connection = c; + iks_filter_add_rule(c->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://www.google.com/session", IKS_RULE_DONE); + iks_filter_add_rule(c->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://jabber.org/protocol/gtalk", IKS_RULE_DONE); + ao2_unlock(member); + ao2_link(gtalk_list, member); + ao2_unlock(c); }); } else { - ASTOBJ_UNLOCK(member); - ASTOBJ_UNREF(member, gtalk_member_destroy); + ao2_unlock(member); + ao2_t_ref(member, -1, "Dec member because unused"); } } else { - ASTOBJ_UNLOCK(member); + ao2_unlock(member); if (gtalk_create_member(cat, var, allowguest, prefs, context, member)) - ASTOBJ_CONTAINER_LINK(>alk_list, member); - ASTOBJ_UNREF(member, gtalk_member_destroy); + ao2_link(>alk_list, member); + ao2_t_ref(member, -1, "remove gtalk member"); } } cat = ast_category_browse(cfg, cat); @@ -1968,7 +1977,7 @@ return AST_MODULE_LOAD_DECLINE; } - ASTOBJ_CONTAINER_INIT(>alk_list); + gtalk_list = ao2_t_container_alloc(hash_gtalk_list, gtalk_list_cb, gtalk_list_cmp_cb, "allocate gtalk peers"); if (!gtalk_load_config()) { ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", GOOGLE_CONFIG); return 0; @@ -2008,6 +2017,9 @@ static int unload_module(void) { struct gtalk_pvt *privates = NULL; + struct ao2_iterator i; + struct gtalk *g; + ast_cli_unregister_multiple(gtalk_cli, sizeof(gtalk_cli) / sizeof(gtalk_cli[0])); /* First, take us out of the channel loop */ ast_channel_unregister(>alk_tech); @@ -2015,24 +2027,31 @@ if (!ast_mutex_lock(>alklock)) { /* Hangup all interfaces if they have an owner */ - ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { - ASTOBJ_WRLOCK(iterator); - privates = iterator->p; + i = ao2_iterator_init(gtalk_list,0); + while (g = ao2_t_iterator_next(&i, "iterate thru gtalk list")) { + ao2_lock(g) + privates = g->p; while(privates) { if (privates->owner) ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD); privates = privates->next; } iterator->p = NULL; - ASTOBJ_UNLOCK(iterator); - }); + ao2_unlock(g); + ao2_t_ref(g, -1, "toss gtalk ptr from iterator_next"); + } ast_mutex_unlock(>alklock); } else { ast_log(LOG_WARNING, "Unable to lock the monitor\n"); return -1; } - ASTOBJ_CONTAINER_DESTROYALL(>alk_list, gtalk_member_destroy); - ASTOBJ_CONTAINER_DESTROY(>alk_list); + + i = ao2_iterator_init(gtalk_list, 0); + + while((g = ao2_t_iterator_next(&i,"iterate through gtalk_list"))) { + gtalk_unlink_all(g, TRUE, TRUE); + ao2_t_ref(g, -1, "throw iterator result"); + } return 0; } Index: include/asterisk/jabber.h =================================================================== --- include/asterisk/jabber.h (revision 114698) +++ include/asterisk/jabber.h (working copy) @@ -122,23 +122,14 @@ }; struct aji_buddy { - ASTOBJ_COMPONENTS_FULL(struct aji_buddy, AJI_MAX_JIDLEN, 1); + struct ao2_container *ajibuddy; char channel[160]; struct aji_resource *resources; enum aji_btype btype; struct ast_flags flags; }; -struct aji_buddy_container { - ASTOBJ_CONTAINER_COMPONENTS(struct aji_buddy); -}; - -struct aji_transport_container { - ASTOBJ_CONTAINER_COMPONENTS(struct aji_transport); -}; - struct aji_client { - ASTOBJ_COMPONENTS(struct aji_client); char password[160]; char user[AJI_MAX_JIDLEN]; char serverhost[AJI_MAX_RESJIDLEN]; @@ -169,7 +160,7 @@ int authorized; struct ast_flags flags; int component; /* 0 client, 1 component */ - struct aji_buddy_container buddies; + struct ao2_container *buddies; AST_LIST_HEAD(messages,aji_message) messages; void *jingle; pthread_t thread; @@ -177,10 +168,6 @@ enum ikshowtype status; }; -struct aji_client_container{ - ASTOBJ_CONTAINER_COMPONENTS(struct aji_client); -}; - /* !Send XML stanza over the established XMPP connection */ int ast_aji_send(struct aji_client *client, iks *x); /*! Send jabber chat message from connected client to jabber URI */ Index: res/res_jabber.c =================================================================== --- res/res_jabber.c (revision 114698) +++ res/res_jabber.c (working copy) @@ -145,12 +145,27 @@ " In order, Online, Chatty, Away, XAway, DND, Offline\n" " If not in roster variable will = 7\n"; -struct aji_client_container clients; +struct ao2_container *clients; struct aji_capabilities *capabilities = NULL; /*! \brief Global flags, initialized to default values */ static struct ast_flags globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER }; +static struct aji_buddy *buddy_ref(struct aji_buddy *b, char *tag) +{ + if (b) + ao2_ref(b, 1); + else + ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n"); + return b; +} + +static void *buddy_unref(struct aji_buddy *b, char *tag) +{ + if (b) + ao2_ref(b, -1); +} + /*! * \brief Deletes the aji_client data structure. * \param obj aji_client The structure we will delete. @@ -159,8 +174,16 @@ static void aji_client_destroy(struct aji_client *obj) { struct aji_message *tmp; - ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, aji_buddy_destroy); - ASTOBJ_CONTAINER_DESTROY(&obj->buddies); + struct aji_client *o; + struct ao2_iterator iter; + + iter = ao2_iterator_init(obj->buddies, 0); + + while( (o = ao2_iterator_next(&iter)) ) { + ao2_unlink(buddies, o); + ao2_ref(o, -1); + } + iks_filter_delete(obj->f); iks_parser_delete(obj->p); iks_stack_delete(obj->stack); @@ -371,7 +394,8 @@ ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); return -1; } - buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); + + buddy = ao2_callback(client->buddies, OBJ_POINTER, buddies_cmp_fn, jid.screenname); if (!buddy) { ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); return -1; @@ -420,7 +444,9 @@ ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); return -1; } - buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); + + buddy = ao2_callback(client->buddies, OBJ_POINTER, buddies_cmp_fn, jid.screenname); + if (!buddy) { ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); return -1; @@ -738,7 +764,9 @@ */ static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming) { - struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); + /*XXX WHAT TO DO BOUT THESE??*/ + struct aji_client *client = (struct aji_client *) data; + ao2_ref(client, 1); if (!ast_strlen_zero(xmpp)) manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp); @@ -755,7 +783,7 @@ } } - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_ref(client, -1); } /*! @@ -818,10 +846,11 @@ */ static int aji_act_hook(void *data, int type, iks *node) { - struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); + struct aji_client *client = (struct aji_client *) data; ikspak *pak = NULL; iks *auth = NULL; int features = 0; + ao2_ref(client, 1); if(!node) { ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */ @@ -842,7 +871,7 @@ if (client->usetls && !aji_is_secure(client)) { if (aji_start_tls(client) == IKS_NET_TLSFAIL) { ast_log(LOG_ERROR, "OpenSSL not installed. You need to install OpenSSL on this system\n"); - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_ref(client, -1); return IKS_HOOK; } @@ -909,7 +938,7 @@ ret = aji_start_sasl(client, features, client->jid->user, client->password); if (ret != IKS_OK) { - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_ref(client, -1); return IKS_HOOK; } break; @@ -924,12 +953,12 @@ break; case IKS_NODE_ERROR: ast_log(LOG_ERROR, "JABBER: Node Error\n"); - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_ref(client, -1); return IKS_HOOK; break; case IKS_NODE_STOP: ast_log(LOG_WARNING, "JABBER: Disconnected\n"); - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_ref(client, -1); return IKS_HOOK; break; } @@ -962,12 +991,12 @@ case IKS_NODE_ERROR: ast_log(LOG_ERROR, "JABBER: Node Error\n"); - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_ref(client, -1); return IKS_HOOK; case IKS_NODE_STOP: ast_log(LOG_WARNING, "JABBER: Disconnected\n"); - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_ref(client, -1); return IKS_HOOK; } } @@ -1002,7 +1031,7 @@ if (node) iks_delete(node); - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_ref(client, -1); return IKS_OK; } /*! @@ -1013,9 +1042,10 @@ */ static int aji_register_approve_handler(void *data, ikspak *pak) { - struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); + struct aji_client *client = (struct aji_client *) data; iks *iq = NULL, *presence = NULL, *x = NULL; + ao2_ref(client, 1); iq = iks_new("iq"); presence = iks_new("presence"); x = iks_new("x"); @@ -1045,7 +1075,7 @@ iks_delete(presence); iks_delete(x); - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_ref(client, -1); return IKS_FILTER_EAT; } /*! @@ -1056,13 +1086,13 @@ */ static int aji_register_query_handler(void *data, ikspak *pak) { - struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); + struct aji_client *client = (struct aji_client *) data; struct aji_buddy *buddy = NULL; char *node = NULL; - client = (struct aji_client *) data; + ao2_ref(client, 1); - buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); + buddy = ao_callback(client->buddies, OBJ_POINTER, buddies_cmp_fn, pak->from->partial); if (!buddy) { iks *iq = NULL, *query = NULL, *error = NULL, *notacceptable = NULL; @@ -1116,7 +1146,7 @@ iks_delete(query); iks_delete(instructions); } - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_ref(client, -1); return IKS_FILTER_EAT; } @@ -2097,11 +2127,15 @@ while (x) { flag = 0; if (iks_strcmp(iks_name(x), "item") == 0) { - ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { - ASTOBJ_RDLOCK(iterator); - if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) + /* XXX */ + ao2_iterator buddy_iter; + struct aji_buddy *buddie; + buddy_iter = ao2_iterator_init(client->buddies, 0); + + while(buddie = ao2_iterator_next(&buddy_iter)) { + if (!strcasecmp(buddie->name, iks_find_attrib(x, "jid"))) flag = 1; - ASTOBJ_UNLOCK(iterator); + ao2_ref(client->buddies, -1); }); if (!flag) { @@ -2122,7 +2156,7 @@ ASTOBJ_UNLOCK(buddy); if (buddy) { ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); - ASTOBJ_UNREF(buddy, aji_buddy_destroy); + ao2_ref(buddy, -1); } } } @@ -2492,8 +2526,9 @@ */ static char *aji_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - struct aji_client *client; + struct aji_client *client, tmp_client; struct aji_resource *resource; + struct ao2_iterator iter; const char *name = "asterisk"; struct aji_message *tmp; @@ -2514,17 +2549,21 @@ else if (a->argc == 3) name = a->argv[2]; - if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { + ast_copy_string(tmp_client.name, name, sizeof(tmp_client.name)); + + if (!(client = ao2_find(clients, &tmp_client, OBJ_POINTER))) { ast_cli(a->fd, "Unable to find client '%s'!\n", name); return CLI_FAILURE; } /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */ ast_aji_send_chat(client, "mogorman@astjab.org", "blahblah"); - ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { - ASTOBJ_RDLOCK(iterator); + iter = ao2_iterator_init(client->buddies, 0); + + while((j = ao2_iterator_next(&iter))) { + ao2_lock(j); ast_verbose("User: %s\n", iterator->name); - for (resource = iterator->resources; resource; resource = resource->next) { + for (resource = j->resources; resource; resource = resource->next) { ast_verbose("Resource: %s\n", resource->resource); if(resource->cap) { ast_verbose(" client: %s\n", resource->cap->parent->node); @@ -2535,15 +2574,15 @@ ast_verbose(" Status: %d\n", resource->status); ast_verbose(" Message: %s\n", S_OR(resource->description,"")); } - ASTOBJ_UNLOCK(iterator); - }); + ao2_unlock(j); + } ast_verbose("\nOooh a working message stack!\n"); AST_LIST_LOCK(&client->messages); AST_LIST_TRAVERSE(&client->messages, tmp, list) { ast_verbose(" Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, "")); } AST_LIST_UNLOCK(&client->messages); - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_unref(client, -1); return CLI_SUCCESS; } @@ -2558,25 +2597,27 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug) { char *resource; - struct aji_client *client = NULL; + struct aji_client tmp_client, *client = NULL; int flag = 0; - client = ASTOBJ_CONTAINER_FIND(&clients,label); + ast_copy_string(tmp_client.name, label, sizeof(tmp_client.name)); + client = ao2_find(clients, &tmp_client, OBJ_POINTER); + if (!client) { flag = 1; - client = ast_calloc(1, sizeof(*client)); + client = ao2_t_alloc(sizeof(*client), client_destroy); if (!client) { ast_log(LOG_ERROR, "Out of memory!\n"); return 0; } - ASTOBJ_INIT(client); - ASTOBJ_WRLOCK(client); - ASTOBJ_CONTAINER_INIT(&client->buddies); + ao2_t_link(clients, client, "add client"); + ao2_lock(client); + client->buddies = ao2_t_container_alloc(hash_buddies_size, buddies_hash_cb, buddies_cmp_cb, "allocate buddies"); } else { - ASTOBJ_WRLOCK(client); - ASTOBJ_UNMARK(client); + ao2_lock(client); + // ASTOBJ_UNMARK(client); } - ASTOBJ_CONTAINER_MARKALL(&client->buddies); + //ASTOBJ_CONTAINER_MARKALL(&client->buddies); ast_copy_string(client->name, label, sizeof(client->name)); ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); @@ -2675,8 +2716,8 @@ var = var->next; } if (!flag) { - ASTOBJ_UNLOCK(client); - ASTOBJ_UNREF(client, aji_client_destroy); + ao2_unlock(client); + ao2_unref(client, -1); return 1; } @@ -2723,8 +2764,8 @@ } else client->jid = iks_id_new(client->stack, client->user); iks_set_log_hook(client->p, aji_log_hook); - ASTOBJ_UNLOCK(client); - ASTOBJ_CONTAINER_LINK(&clients,client); + ao2_unlock(client); + ao2_t_link(&clients,client); return 1; } @@ -2867,10 +2908,6 @@ return client; } -struct aji_client_container *ast_aji_get_clients(void) -{ - return &clients; -} static char mandescr_jabber_send[] = "Description: Sends a message to a Jabber Client.\n" @@ -2966,21 +3003,6 @@ ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); iterator->state = AJI_DISCONNECTING; ast_aji_disconnect(iterator); - pthread_join(iterator->thread, NULL); - ASTOBJ_UNLOCK(iterator); - }); - - ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy); - ASTOBJ_CONTAINER_DESTROY(&clients); - return 0; -} - -/*! \brief Unload the jabber module */ -static int load_module(void) -{ - ASTOBJ_CONTAINER_INIT(&clients); - if(!aji_reload(0)) - return AST_MODULE_LOAD_DECLINE; ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send, "Sends a message to a Jabber Client", mandescr_jabber_send); ast_register_application(app_ajisend, aji_send_exec, ajisend_synopsis, ajisend_descrip);