diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index c781f37a62f98337ec61529796fa8f4c9d002d63..ad5ed7013853bf96de53c348df7864f8dca0d7ac 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -786,11 +786,11 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags, /* Set up the iterator we'll be using during this call */ if (!ast_strlen_zero(spec)) { - iter = ast_channel_iterator_by_name_new(0, spec, strlen(spec)); + iter = ast_channel_iterator_by_name_new(spec, strlen(spec)); } else if (!ast_strlen_zero(exten)) { - iter = ast_channel_iterator_by_exten_new(0, exten, context); + iter = ast_channel_iterator_by_exten_new(exten, context); } else { - iter = ast_channel_iterator_all_new(0); + iter = ast_channel_iterator_all_new(); } if (!iter) { diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c index a6ca09ac5f740fd3362f63c1c6f7dfc94f15cf91..bc25defe2dfdf2cb671a2da53695c1f2fa80e7c2 100644 --- a/apps/app_directed_pickup.c +++ b/apps/app_directed_pickup.c @@ -210,7 +210,7 @@ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const ch struct ast_channel_iterator *iter; int res = -1; - if (!(iter = ast_channel_iterator_by_exten_new(0, exten, context))) { + if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) { return -1; } @@ -223,6 +223,8 @@ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const ch target = ast_channel_unref(target); } + ast_channel_iterator_destroy(iter); + if (target) { res = pickup_do(chan, target); ast_channel_unlock(target); diff --git a/apps/app_softhangup.c b/apps/app_softhangup.c index 50bdb6809dc519c9065bd7f70a6560717640e17b..3513bb775446c635c7893f0d81bc209c43006131 100644 --- a/apps/app_softhangup.c +++ b/apps/app_softhangup.c @@ -94,7 +94,7 @@ static int softhangup_exec(struct ast_channel *chan, const char *data) ast_app_parse_options(app_opts, &flags, opts, args.options); lenmatch = strlen(args.channel); - if (!(iter = ast_channel_iterator_by_name_new(0, args.channel, lenmatch))) { + if (!(iter = ast_channel_iterator_by_name_new(args.channel, lenmatch))) { return -1; } diff --git a/funcs/func_channel.c b/funcs/func_channel.c index e82c39a51cf104c549f3b0b3b87bab7ef7437da8..f20bfcaa14454eceee1a6b44b55f39b4877f2d01 100644 --- a/funcs/func_channel.c +++ b/funcs/func_channel.c @@ -465,7 +465,7 @@ static int func_channels_read(struct ast_channel *chan, const char *function, ch } } - if (!(iter = ast_channel_iterator_all_new(0))) { + if (!(iter = ast_channel_iterator_all_new())) { if (!ast_strlen_zero(data)) { regfree(&re); } diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h index f0393d34f14c382530692efce3b12e4df8a427e7..6caa4a7c4374719c1fd27f07769f7cb6eede50ea 100644 --- a/include/asterisk/astobj2.h +++ b/include/asterisk/astobj2.h @@ -18,6 +18,7 @@ #define _ASTERISK_ASTOBJ2_H #include "asterisk/compat.h" +#include "asterisk/linkedlists.h" /*! \file * \ref AstObj2 @@ -547,7 +548,7 @@ Operations on container include: can be: OBJ_UNLINK - to remove the object, once found, from the container. OBJ_NODATA - don't return the object if found (no ref count change) - OBJ_MULTIPLE - don't stop at first match (not fully implemented) + OBJ_MULTIPLE - don't stop at first match OBJ_POINTER - if set, 'arg' is an object pointer, and a hashtable search will be done. If not, a traversal is done. @@ -559,7 +560,7 @@ Operations on container include: - flags can be OBJ_UNLINK - to remove the object, once found, from the container. OBJ_NODATA - don't return the object if found (no ref count change) - OBJ_MULTIPLE - don't stop at first match (not fully implemented) + OBJ_MULTIPLE - don't stop at first match OBJ_POINTER - if set, 'arg' is an object pointer, and a hashtable search will be done. If not, a traversal is done through all the hashtable 'buckets'.. @@ -658,22 +659,21 @@ enum _cb_results { */ enum search_flags { /*! Unlink the object for which the callback function - * returned CMP_MATCH . This is the only way to extract - * objects from a container. */ + * returned CMP_MATCH. + */ OBJ_UNLINK = (1 << 0), /*! On match, don't return the object hence do not increase - * its refcount. */ + * its refcount. + */ OBJ_NODATA = (1 << 1), - /*! Don't stop at the first match in ao2_callback() - * \note This is not fully implemented. Using OBJ_MULTIME with OBJ_NODATA - * is perfectly fine. The part that is not implemented is the case where - * multiple objects should be returned by ao2_callback(). + /*! Don't stop at the first match in ao2_callback(). */ OBJ_MULTIPLE = (1 << 2), /*! obj is an object of the same type as the one being searched for, * so use the object's hash function for optimized searching. * The search function is unaffected (i.e. use the one passed as - * argument, or match_by_addr if none specified). */ + * argument, or match_by_addr if none specified). + */ OBJ_POINTER = (1 << 3), /*! * \brief Continue if a match is not found in the hashed out bucket @@ -817,12 +817,6 @@ void *__ao2_unlink_debug(struct ao2_container *c, void *obj, char *tag, char *fi void *__ao2_unlink(struct ao2_container *c, void *obj); -/*! \brief Used as return value if the flag OBJ_MULTIPLE is set */ -struct ao2_list { - struct ao2_list *next; - void *obj; /* pointer to the user portion of the object */ -}; - /*@} */ /*! \brief @@ -847,21 +841,22 @@ struct ao2_list { should immediately stop, or both (via bitwise ORing), if you find a match and want to end the traversal, and 0 if the object is not a match, but the traversal should continue. This is the function that is applied - to each object traversed. It's arguments are: + to each object traversed. Its arguments are: (void *obj, void *arg, int flags), where: obj is an object arg is the same as arg passed into ao2_callback flags is the same as flags passed into ao2_callback (flags are also used by ao2_callback). * \param arg passed to the callback. - * \return A pointer to the object found/marked, - * a pointer to a list of objects matching comparison function, - * NULL if not found. + * \return when OBJ_MULTIPLE is not included in the flags parameter, + * the return value will be either the object found or NULL if no + * no matching object was found. if OBJ_MULTIPLE is included, + * the return value will be a pointer to an ao2_iterator object, + * which must be destroyed with ao2_iterator_destroy() when the + * caller no longer needs it. * * If the function returns any objects, their refcount is incremented, * and the caller is in charge of decrementing them once done. - * Also, in case of multiple values returned, the list used - * to store the objects must be freed by the caller. * * Typically, ao2_callback() is used for two purposes: * - to perform some action (including removal from the container) on one @@ -881,9 +876,7 @@ struct ao2_list { * we can say this looking at flags value. * If p points to an object we will search for the object pointed * by this value, otherwise we serch for a key value. - * If the key is not uniq we only find the first matching valued. - * If we use the OBJ_MARK flags, we mark all the objects matching - * the condition. + * If the key is not unique we only find the first matching valued. * * The use of flags argument is the follow: * @@ -892,13 +885,9 @@ struct ao2_list { * Callbacks use OBJ_NODATA as a default * functions such as find() do * OBJ_MULTIPLE return multiple matches - * Default for _find() is no. - * to a key (not yet supported) + * Default is no. * OBJ_POINTER the pointer is an object pointer * - * In case we return a list, the callee must take care to destroy - * that list when no longer used. - * * \note When the returned object is no longer in use, ao2_ref() should * be used to free the additional reference possibly created by this function. * @@ -1078,6 +1067,15 @@ enum ao2_iterator_flags { * while retrieving the next object from it. */ AO2_ITERATOR_DONTLOCK = (1 << 0), + /*! Indicates that the iterator was dynamically allocated by + * astobj2 API and should be freed by ao2_iterator_destroy(). + */ + AO2_ITERATOR_MALLOCD = (1 << 1), + /*! Indicates that before the iterator returns an object from + * the container being iterated, the object should be unlinked + * from the container. + */ + AO2_ITERATOR_UNLINK = (1 << 2), }; /*! diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index cab334685dc7da7fd61a029835ed45cfd8b45e7a..2b285ba8d98a31ce995493ae783d63ab5cb41acd 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -2210,7 +2210,6 @@ struct ast_channel_iterator *ast_channel_iterator_destroy(struct ast_channel_ite /*! * \brief Create a new channel iterator based on extension * - * \arg ao2_flags astobj2 iterator flags * \arg exten The extension that channels must be in * \arg context The context that channels must be in (optional) * @@ -2223,13 +2222,11 @@ struct ast_channel_iterator *ast_channel_iterator_destroy(struct ast_channel_ite * * \since 1.6.3 */ -struct ast_channel_iterator *ast_channel_iterator_by_exten_new(int ao2_flags, const char *exten, - const char *context); +struct ast_channel_iterator *ast_channel_iterator_by_exten_new(const char *exten, const char *context); /*! * \brief Create a new channel iterator based on name * - * \arg ao2_flags astobj2 iterator flags * \arg name channel name or channel uniqueid to match * \arg name_len number of characters in the channel name to match on. This * would be used to match based on name prefix. If matching on the full @@ -2244,14 +2241,11 @@ struct ast_channel_iterator *ast_channel_iterator_by_exten_new(int ao2_flags, co * * \since 1.6.3 */ -struct ast_channel_iterator *ast_channel_iterator_by_name_new(int ao2_flags, const char *name, - size_t name_len); +struct ast_channel_iterator *ast_channel_iterator_by_name_new(const char *name, size_t name_len); /*! * \brief Create a new channel iterator * - * \arg ao2_flags astobj2 iterator flags - * * After creating an iterator using this function, the ast_channel_iterator_next() * function can be used to iterate through all channels that exist. * @@ -2260,7 +2254,7 @@ struct ast_channel_iterator *ast_channel_iterator_by_name_new(int ao2_flags, con * * \since 1.6.3 */ -struct ast_channel_iterator *ast_channel_iterator_all_new(int ao2_flags); +struct ast_channel_iterator *ast_channel_iterator_all_new(void); /*! * \brief Get the next channel for a channel iterator diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h index bfbed1e6f500ec975e459a2e76321c2752878274..4785a7636c6ba18abf46620524b2d594c819505d 100644 --- a/include/asterisk/lock.h +++ b/include/asterisk/lock.h @@ -60,7 +60,6 @@ #endif #include "asterisk/logger.h" -#include "asterisk/astobj2.h" /* internal macro to profile mutexes. Only computes the delay on * non-blocking calls. diff --git a/main/astobj2.c b/main/astobj2.c index 01fd4b17fcb455eabe8f2cbade9436b407e73c04..cecef7c66f03833ec94258187b497244962a7d63 100644 --- a/main/astobj2.c +++ b/main/astobj2.c @@ -292,7 +292,7 @@ static int internal_ao2_ref(void *user_data, const int delta) * first word of the user-data, which we make sure is always * allocated. */ memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) ); - free(obj); + ast_free(obj); } return ret; @@ -609,13 +609,27 @@ static void *internal_ao2_callback(struct ao2_container *c, void *ret = NULL; ao2_callback_fn *cb_default = NULL; ao2_callback_data_fn *cb_withdata = NULL; + struct ao2_container *multi_container = NULL; + struct ao2_iterator *multi_iterator = NULL; if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */ return NULL; if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) { - ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags); - return NULL; + /* we need to return an ao2_iterator with the results, + * as there could be more than one. the iterator will + * hold the only reference to a container that has all the + * matching objects linked into it, so when the iterator + * is destroyed, the container will be automatically + * destroyed as well. + */ + if (!(multi_container = __ao2_container_alloc(1, NULL, NULL))) { + return NULL; + } + if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) { + ao2_ref(multi_container, -1); + return NULL; + } } /* override the match function if necessary */ @@ -627,7 +641,7 @@ static void *internal_ao2_callback(struct ao2_container *c, } } else { /* We do this here to avoid the per object casting penalty (even though - that is probably optimized away anyway. */ + that is probably optimized away anyway). */ if (type == WITH_DATA) { cb_withdata = cb_fn; } else { @@ -678,49 +692,51 @@ static void *internal_ao2_callback(struct ao2_container *c, i = last; break; } + /* we have a match (CMP_MATCH) here */ if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */ /* it is important to handle this case before the unlink */ ret = EXTERNAL_OBJ(cur->astobj); - if (tag) - __ao2_ref_debug(ret, 1, tag, file, line, funcname); - else - __ao2_ref(ret, 1); + if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) { + if (tag) + __ao2_ref_debug(ret, 1, tag, file, line, funcname); + else + __ao2_ref(ret, 1); + } } - if (flags & OBJ_UNLINK) { /* must unlink */ - struct bucket_list *x = cur; + /* if we are in OBJ_MULTIPLE mode, link the object into the + * container that will hold the results + */ + if (ret && (multi_container != NULL)) { + __ao2_link(multi_container, ret); + ret = NULL; + } + if (flags & OBJ_UNLINK) { /* must unlink */ /* we are going to modify the container, so update version */ ast_atomic_fetchadd_int(&c->version, 1); AST_LIST_REMOVE_CURRENT(entry); - /* update number of elements and version */ + /* update number of elements */ ast_atomic_fetchadd_int(&c->elements, -1); - if (tag) - __ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname); - else - __ao2_ref(EXTERNAL_OBJ(x->astobj), -1); - free(x); /* free the link record */ + if (!(flags & OBJ_NODATA)) { + if (tag) + __ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, funcname); + else + __ao2_ref(EXTERNAL_OBJ(cur->astobj), -1); + } + ast_free(cur); /* free the link record */ } - if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) { + if ((match & CMP_STOP) || (multi_container == NULL)) { /* We found the only match we need */ i = last; /* force exit from outer loop */ break; } - if (!(flags & OBJ_NODATA)) { -#if 0 /* XXX to be completed */ - /* - * This is the multiple-return case. We need to link - * the object in a list. The refcount is already increased. - */ -#endif - } } AST_LIST_TRAVERSE_SAFE_END; if (ret) { - /* This assumes OBJ_MULTIPLE with !OBJ_NODATA is still not implemented */ break; } @@ -731,7 +747,14 @@ static void *internal_ao2_callback(struct ao2_container *c, } } ao2_unlock(c); - return ret; + if (multi_container != NULL) { + *multi_iterator = ao2_iterator_init(multi_container, + AO2_ITERATOR_DONTLOCK | AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD); + ao2_ref(multi_container, -1); + return multi_iterator; + } else { + return ret; + } } void *__ao2_callback_debug(struct ao2_container *c, @@ -796,7 +819,11 @@ struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) void ao2_iterator_destroy(struct ao2_iterator *i) { ao2_ref(i->c, -1); - i->c = NULL; + if (i->flags & AO2_ITERATOR_MALLOCD) { + ast_free(i); + } else { + i->c = NULL; + } } /* @@ -819,8 +846,8 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *a, struct bucket_li /* optimization. If the container is unchanged and * we have a pointer, try follow it */ - if (a->c->version == a->c_version && (p = a->obj) ) { - if ( (p = AST_LIST_NEXT(p, entry)) ) + if (a->c->version == a->c_version && (p = a->obj)) { + if ((p = AST_LIST_NEXT(p, entry))) goto found; /* nope, start from the next bucket */ a->bucket++; @@ -846,12 +873,24 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *a, struct bucket_li found: if (p) { - a->version = p->version; - a->obj = p; - a->c_version = a->c->version; ret = EXTERNAL_OBJ(p->astobj); - /* inc refcount of returned object */ - *q = p; + if (a->flags & AO2_ITERATOR_UNLINK) { + /* we are going to modify the container, so update version */ + ast_atomic_fetchadd_int(&a->c->version, 1); + AST_LIST_REMOVE(&a->c->buckets[a->bucket], p, entry); + /* update number of elements */ + ast_atomic_fetchadd_int(&a->c->elements, -1); + a->version = 0; + a->obj = NULL; + a->c_version = a->c->version; + ast_free(p); + } else { + a->version = p->version; + a->obj = p; + a->c_version = a->c->version; + /* inc refcount of returned object */ + *q = p; + } } return ret; diff --git a/main/channel.c b/main/channel.c index 60ad9638b6570942f8ed6b74c9a608b8d4a5c740..af904692ae5f580adba17796a2533598e8455b6b 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1234,137 +1234,83 @@ struct ast_channel *ast_channel_callback(ao2_callback_data_fn *cb_fn, void *arg, } struct ast_channel_iterator { - struct ao2_iterator i; - const char *name; - size_t name_len; - const char *exten; - const char *context; + /* storage for non-dynamically allocated iterator */ + struct ao2_iterator simple_iterator; + /* pointer to the actual iterator (simple_iterator or a dynamically + * allocated iterator) + */ + struct ao2_iterator *active_iterator; }; struct ast_channel_iterator *ast_channel_iterator_destroy(struct ast_channel_iterator *i) { - if (i->name) { - ast_free((void *) i->name); - i->name = NULL; - } - - if (i->exten) { - ast_free((void *) i->exten); - i->exten = NULL; - } - - if (i->context) { - ast_free((void *) i->context); - i->context = NULL; - } - + ao2_iterator_destroy(i->active_iterator); ast_free(i); return NULL; } -static struct ast_channel_iterator *ast_channel_iterator_new(int ao2_flags, const char *name, - size_t name_len, const char *exten, const char *context) +static struct ast_channel_iterator *channel_iterator_search(const char *name, + size_t name_len, const char *exten, + const char *context) { struct ast_channel_iterator *i; + struct ast_channel tmp_chan = { + .name = name, + /* This is sort of a hack. Basically, we're using an arbitrary field + * in ast_channel to pass the name_len for a prefix match. If this + * gets changed, then the compare callback must be changed, too. */ + .rings = name_len, + }; if (!(i = ast_calloc(1, sizeof(*i)))) { return NULL; } - if (!ast_strlen_zero(exten) && !(i->exten = ast_strdup(exten))) { - goto return_error; + if (exten) { + ast_copy_string(tmp_chan.exten, exten, sizeof(tmp_chan.exten)); } - if (!ast_strlen_zero(context) && !(i->context = ast_strdup(context))) { - goto return_error; + if (context) { + ast_copy_string(tmp_chan.context, context, sizeof(tmp_chan.context)); } - if (!ast_strlen_zero(name) && !(i->name = ast_strdup(name))) { - goto return_error; + if (!(i->active_iterator = ao2_find(channels, &tmp_chan, + OBJ_MULTIPLE | ((!ast_strlen_zero(name) && (name_len == 0)) ? OBJ_POINTER : 0)))) { + ast_free(i); + return NULL; } - i->name_len = name_len; - - i->i = ao2_iterator_init(channels, ao2_flags); - return i; - -return_error: - if (i->exten) { - ast_free((void *) i->exten); - i->exten = NULL; - } - - if (i->context) { - ast_free((void *) i->context); - i->context = NULL; - } - - ast_free(i); - - return NULL; -} - -struct ast_channel_iterator *ast_channel_iterator_by_exten_new(int ao2_flags, const char *exten, - const char *context) -{ - return ast_channel_iterator_new(ao2_flags, NULL, 0, exten, context); } -struct ast_channel_iterator *ast_channel_iterator_by_name_new(int ao2_flags, const char *name, - size_t name_len) +struct ast_channel_iterator *ast_channel_iterator_by_exten_new(const char *exten, const char *context) { - return ast_channel_iterator_new(ao2_flags, name, name_len, NULL, NULL); + return channel_iterator_search(NULL, 0, exten, context); } -struct ast_channel_iterator *ast_channel_iterator_all_new(int ao2_flags) +struct ast_channel_iterator *ast_channel_iterator_by_name_new(const char *name, size_t name_len) { - return ast_channel_iterator_new(ao2_flags, NULL, 0, NULL, NULL); + return channel_iterator_search(name, name_len, NULL, NULL); } -/*! - * \note This function will be reduced to 1 line of code once ao2 supports - * returning multiple objects from an ao2_callback() using OBJ_MULTIPLE. - */ -struct ast_channel *ast_channel_iterator_next(struct ast_channel_iterator *i) +struct ast_channel_iterator *ast_channel_iterator_all_new(void) { - struct ast_channel *chan = NULL; - - for (; (chan = ao2_iterator_next(&i->i)); - ast_channel_unlock(chan), ast_channel_unref(chan)) { - - ast_channel_lock(chan); - - if (i->name) { /* match by name */ - if (!i->name_len) { - if (strcasecmp(chan->name, i->name) && strcasecmp(chan->uniqueid, i->name)) { - continue; /* name match failed */ - } - } else { - if (strncasecmp(chan->name, i->name, i->name_len) && - strncasecmp(chan->uniqueid, i->name, i->name_len)) { - continue; /* name match failed */ - } - } - } else if (i->exten) { - if (i->context && strcasecmp(chan->context, i->context) && - strcasecmp(chan->macrocontext, i->context)) { - continue; /* context match failed */ - } + struct ast_channel_iterator *i; - if (strcasecmp(chan->exten, i->exten) && - strcasecmp(chan->macroexten, i->exten)) { - continue; /* exten match failed */ - } - } + if (!(i = ast_calloc(1, sizeof(*i)))) { + return NULL; + } - ast_channel_unlock(chan); + i->simple_iterator = ao2_iterator_init(channels, 0); + i->active_iterator = &i->simple_iterator; - break; /* chan points to the next chan desired. */ - } + return i; +} - return chan; +struct ast_channel *ast_channel_iterator_next(struct ast_channel_iterator *i) +{ + return ao2_iterator_next(i->active_iterator); } static int ast_channel_cmp_cb(void *obj, void *arg, int flags) @@ -1407,7 +1353,7 @@ static int ast_channel_cmp_cb(void *obj, void *arg, int flags) } static struct ast_channel *ast_channel_get_full(const char *name, size_t name_len, - const char *exten, const char *context) + const char *exten, const char *context) { struct ast_channel tmp_chan = { .name = name, diff --git a/main/cli.c b/main/cli.c index 5b31bba2b497d4b9ad1b1c94a9d79b966b8f65e3..abfc8f0a9e5560ff2d4afcf65489fd446e991d3d 100644 --- a/main/cli.c +++ b/main/cli.c @@ -827,7 +827,7 @@ static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_ar "CallerID", "Duration", "Accountcode", "PeerAccount", "BridgedTo"); } - if (!count && !(iter = ast_channel_iterator_all_new(0))) { + if (!count && !(iter = ast_channel_iterator_all_new())) { return CLI_FAILURE; } @@ -1454,7 +1454,7 @@ char *ast_complete_channels(const char *line, const char *word, int pos, int sta return NULL; } - if (!(iter = ast_channel_iterator_by_name_new(0, word, strlen(word)))) { + if (!(iter = ast_channel_iterator_by_name_new(word, strlen(word)))) { return NULL; } @@ -1467,6 +1467,8 @@ char *ast_complete_channels(const char *line, const char *word, int pos, int sta ast_channel_unref(c); } + ast_channel_iterator_destroy(iter); + return ret == ¬found ? NULL : ret; } diff --git a/main/manager.c b/main/manager.c index 1bd2eaeb4fa5712c9a25af8d6352d59b314e268e..a02d06106d2eb52629007e75f16d41c121c9336c 100644 --- a/main/manager.c +++ b/main/manager.c @@ -2806,7 +2806,7 @@ static int action_status(struct mansession *s, const struct message *m) } if (all) { - if (!(iter = ast_channel_iterator_all_new(0))) { + if (!(iter = ast_channel_iterator_all_new())) { ast_free(str); astman_send_error(s, m, "Memory Allocation Failure"); return 1; @@ -2914,6 +2914,10 @@ static int action_status(struct mansession *s, const struct message *m) } } + if (iter) { + ast_channel_iterator_destroy(iter); + } + astman_append(s, "Event: StatusComplete\r\n" "%s" @@ -3643,7 +3647,7 @@ static int action_coreshowchannels(struct mansession *s, const struct message *m idText[0] = '\0'; } - if (!(iter = ast_channel_iterator_all_new(0))) { + if (!(iter = ast_channel_iterator_all_new())) { astman_send_error(s, m, "Memory Allocation Failure"); return 1; } diff --git a/res/snmp/agent.c b/res/snmp/agent.c index f4d4fc6fd826afecf4903d691071eb569d9c6652..df4523339c0f5ffa16be29ddbf5b22aeb8637213 100644 --- a/res/snmp/agent.c +++ b/res/snmp/agent.c @@ -243,7 +243,7 @@ static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *le i = name[*length - 1] - 1; - if (!(iter = ast_channel_iterator_all_new(0))) { + if (!(iter = ast_channel_iterator_all_new())) { return NULL; } @@ -588,7 +588,7 @@ static u_char *ast_var_channel_types_table(struct variable *vp, oid *name, size_ long_ret = 0; - if (!(iter = ast_channel_iterator_all_new(0))) { + if (!(iter = ast_channel_iterator_all_new())) { return NULL; } @@ -622,7 +622,7 @@ static u_char *ast_var_channel_bridge(struct variable *vp, oid *name, size_t *le return NULL; } - if (!(iter = ast_channel_iterator_all_new(0))) { + if (!(iter = ast_channel_iterator_all_new())) { return NULL; } @@ -635,6 +635,8 @@ static u_char *ast_var_channel_bridge(struct variable *vp, oid *name, size_t *le chan = ast_channel_unref(chan); } + ast_channel_iterator_destroy(iter); + *var_len = sizeof(long_ret); return (vp->magic == ASTCHANBRIDGECOUNT) ? (u_char *) &long_ret : NULL;