/*! \internal * \brief determine if a list of attribute key value pairs are set on a format */ static int format_isset_helper(const struct ast_format *format, va_list ap) { int res; struct interface_ao2_wrapper *wrapper; struct ast_format tmp = { .id = format->id, .fattr = { { 0, }, }, }; if (!(wrapper = find_interface(format))) { return -1; } ao2_rdlock(wrapper); if (!wrapper->interface || !wrapper->interface->format_attr_set || !wrapper->interface->format_attr_cmp) { ao2_unlock(wrapper); ao2_ref(wrapper, -1); return -1; } /* if isset is present, use that function, else just build a new * format and use the cmp function */ if (wrapper->interface->format_attr_isset) { res = wrapper->interface->format_attr_isset(&format->fattr, ap); } else { wrapper->interface->format_attr_set(&tmp.fattr, ap); /* use our tmp structure to tell if the attributes are set or not */ res = wrapper->interface->format_attr_cmp(&tmp.fattr, &format->fattr); res = (res == AST_FORMAT_CMP_NOT_EQUAL) ? -1 : 0; } ao2_unlock(wrapper); ao2_ref(wrapper, -1); return res; } int ast_format_isset(const struct ast_format *format, ... ) { va_list ap; int res; va_start(ap, format); res = format_isset_helper(format, ap); va_end(ap); return res; }
/*! * \internal * \brief Adjust an object's lock to the requested level. * * \param user_data An ao2 object to adjust lock level. * \param lock_how What level to adjust lock. * \param keep_stronger TRUE if keep original lock level if it is stronger. * * \pre The ao2 object is already locked. * * \details * An ao2 object with a RWLOCK will have its lock level adjusted * to the specified level if it is not already there. An ao2 * object with a different type of lock is not affected. * * \return Original lock level. */ enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger) { struct astobj2 *obj = INTERNAL_OBJ(user_data); struct astobj2_rwlock *obj_rwlock; enum ao2_lock_req orig_lock; switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) { case AO2_ALLOC_OPT_LOCK_RWLOCK: obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data); if (obj_rwlock->rwlock.num_lockers < 0) { orig_lock = AO2_LOCK_REQ_WRLOCK; } else { orig_lock = AO2_LOCK_REQ_RDLOCK; } switch (lock_how) { case AO2_LOCK_REQ_MUTEX: lock_how = AO2_LOCK_REQ_WRLOCK; /* Fall through */ case AO2_LOCK_REQ_WRLOCK: if (lock_how != orig_lock) { /* Switch from read lock to write lock. */ ao2_unlock(user_data); ao2_wrlock(user_data); } break; case AO2_LOCK_REQ_RDLOCK: if (!keep_stronger && lock_how != orig_lock) { /* Switch from write lock to read lock. */ ao2_unlock(user_data); ao2_rdlock(user_data); } break; } break; default: ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data); /* Fall through */ case AO2_ALLOC_OPT_LOCK_NOLOCK: case AO2_ALLOC_OPT_LOCK_MUTEX: orig_lock = AO2_LOCK_REQ_MUTEX; break; } return orig_lock; }
/*! \internal * \brief get joint format attributes using an interface */ static int format_joint_helper(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result) { int res = 0; struct interface_ao2_wrapper *wrapper; if (!(wrapper = find_interface(format1))) { /* if no interface is present, we assume formats are joint by id alone */ return res; } ao2_rdlock(wrapper); if (wrapper->interface && wrapper->interface->format_attr_get_joint) { res = wrapper->interface->format_attr_get_joint(&format1->fattr, &format2->fattr, &result->fattr); } ao2_unlock(wrapper); ao2_ref(wrapper, -1); return res; }
/*! \internal * \brief cmp format attributes using an interface */ static enum ast_format_cmp_res format_cmp_helper(const struct ast_format *format1, const struct ast_format *format2) { enum ast_format_cmp_res res = AST_FORMAT_CMP_EQUAL; struct interface_ao2_wrapper *wrapper; if (!(wrapper = find_interface(format1))) { return res; } ao2_rdlock(wrapper); if (!wrapper->interface || !wrapper->interface->format_attr_cmp) { ao2_unlock(wrapper); ao2_ref(wrapper, -1); return res; } res = wrapper->interface->format_attr_cmp(&format1->fattr, &format2->fattr); ao2_unlock(wrapper); ao2_ref(wrapper, -1); return res; }
int ast_format_get_value(const struct ast_format *format, int key, void *value) { int res = 0; struct interface_ao2_wrapper *wrapper; if (!(wrapper = find_interface(format))) { return -1; } ao2_rdlock(wrapper); if (!wrapper->interface || !wrapper->interface->format_attr_get_val) { ao2_unlock(wrapper); ao2_ref(wrapper, -1); return -1; } res = wrapper->interface->format_attr_get_val(&format->fattr, key, value); ao2_unlock(wrapper); ao2_ref(wrapper, -1); return res; }
static char *cli_show_tasks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct ao2_iterator i; struct ast_sip_sched_task *schtd; const char *log_format = ast_logger_get_dateformat(); struct ast_tm tm; char queued[32]; char last_start[32]; char last_end[32]; int datelen; struct timeval now = ast_tvnow(); const char *separator = "======================================"; switch (cmd) { case CLI_INIT: e->command = "pjsip show scheduled_tasks"; e->usage = "Usage: pjsip show scheduled_tasks\n" " Show all scheduled tasks\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 3) { return CLI_SHOWUSAGE; } ast_localtime(&now, &tm, NULL); datelen = ast_strftime(queued, sizeof(queued), log_format, &tm); ast_cli(a->fd, "PJSIP Scheduled Tasks:\n\n"); ast_cli(a->fd, " %1$-24s %2$-8s %3$-9s %4$-7s %6$-*5$s %7$-*5$s %8$-*5$s\n", "Task Name", "Interval", "Times Run", "State", datelen, "Queued", "Last Started", "Last Ended"); ast_cli(a->fd, " %1$-24.24s %2$-8.8s %3$-9.9s %4$-7.7s %6$-*5$.*5$s %7$-*5$.*5$s %8$-*5$.*5$s\n", separator, separator, separator, separator, datelen, separator, separator, separator); ao2_ref(tasks, +1); ao2_rdlock(tasks); i = ao2_iterator_init(tasks, 0); while ((schtd = ao2_iterator_next(&i))) { ast_localtime(&schtd->when_queued, &tm, NULL); ast_strftime(queued, sizeof(queued), log_format, &tm); if (ast_tvzero(schtd->last_start)) { strcpy(last_start, "not yet started"); } else { ast_localtime(&schtd->last_start, &tm, NULL); ast_strftime(last_start, sizeof(last_start), log_format, &tm); } if (ast_tvzero(schtd->last_end)) { if (ast_tvzero(schtd->last_start)) { strcpy(last_end, "not yet started"); } else { strcpy(last_end, "running"); } } else { ast_localtime(&schtd->last_end, &tm, NULL); ast_strftime(last_end, sizeof(last_end), log_format, &tm); } ast_cli(a->fd, " %1$-24.24s %2$-8.3f %3$-9d %4$-7s %6$-*5$s %7$-*5$s %8$-*5$s\n", schtd->name, schtd->interval / 1000.0, schtd->run_count, schtd->is_running ? "running" : "waiting", datelen, queued, last_start, last_end); ao2_cleanup(schtd); } ao2_iterator_destroy(&i); ao2_unlock(tasks); ao2_ref(tasks, -1); ast_cli(a->fd, "\n"); return CLI_SUCCESS; }
static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct ao2_iterator i; struct ast_codec *codec; switch (cmd) { case CLI_INIT: e->command = "core show codecs [audio|video|image|text]"; e->usage = "Usage: core show codecs [audio|video|image|text]\n" " Displays codec mapping\n"; return NULL; case CLI_GENERATE: return NULL; } if ((a->argc < 3) || (a->argc > 4)) { return CLI_SHOWUSAGE; } if (!ast_opt_dont_warn) { ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n" "\tIt does not indicate anything about your configuration.\n"); } ast_cli(a->fd, "%8s %5s %8s %s\n","ID","TYPE","NAME","DESCRIPTION"); ast_cli(a->fd, "-----------------------------------------------------------------------------------\n"); ao2_rdlock(codecs); i = ao2_iterator_init(codecs, AO2_ITERATOR_DONTLOCK); for (; (codec = ao2_iterator_next(&i)); ao2_ref(codec, -1)) { if (a->argc == 4) { if (!strcasecmp(a->argv[3], "audio")) { if (codec->type != AST_MEDIA_TYPE_AUDIO) { continue; } } else if (!strcasecmp(a->argv[3], "video")) { if (codec->type != AST_MEDIA_TYPE_VIDEO) { continue; } } else if (!strcasecmp(a->argv[3], "image")) { if (codec->type != AST_MEDIA_TYPE_IMAGE) { continue; } } else if (!strcasecmp(a->argv[3], "text")) { if (codec->type != AST_MEDIA_TYPE_TEXT) { continue; } } else { continue; } } ast_cli(a->fd, "%8u %5s %8s (%s)\n", codec->id, ast_codec_media_type2str(codec->type), codec->name, codec->description); } ao2_iterator_destroy(&i); ao2_unlock(codecs); return CLI_SUCCESS; }
static struct interface_ao2_wrapper *find_interface(const struct ast_format *format) { struct interface_ao2_wrapper tmp_wrapper = { .id = format->id, }; return ao2_find(interfaces, &tmp_wrapper, OBJ_POINTER); } static int has_interface(const struct ast_format *format) { struct interface_ao2_wrapper *wrapper; wrapper = find_interface(format); if (!wrapper) { return 0; } ao2_ref(wrapper, -1); return 1; } int ast_format_sdp_parse(struct ast_format *format, const char *attributes) { struct interface_ao2_wrapper *wrapper; int res; if (!(wrapper = find_interface(format))) { return 0; } ao2_rdlock(wrapper); if (!(wrapper->interface || !wrapper->interface->format_attr_sdp_parse)) { ao2_unlock(wrapper); ao2_ref(wrapper, -1); return 0; } res = wrapper->interface->format_attr_sdp_parse(&format->fattr, attributes); ao2_unlock(wrapper); ao2_ref(wrapper, -1); return res; } void ast_format_sdp_generate(const struct ast_format *format, unsigned int payload, struct ast_str **str) { struct interface_ao2_wrapper *wrapper; if (!(wrapper = find_interface(format))) { return; } ao2_rdlock(wrapper); if (!(wrapper->interface || !wrapper->interface->format_attr_sdp_generate)) { ao2_unlock(wrapper); ao2_ref(wrapper, -1); return; } wrapper->interface->format_attr_sdp_generate(&format->fattr, payload, str); ao2_unlock(wrapper); ao2_ref(wrapper, -1); } /*! \internal * \brief set format attributes using an interface */ static int format_set_helper(struct ast_format *format, va_list ap) { struct interface_ao2_wrapper *wrapper; if (!(wrapper = find_interface(format))) { ast_log(LOG_WARNING, "Could not find format interface to set.\n"); return -1; } ao2_rdlock(wrapper); if (!wrapper->interface || !wrapper->interface->format_attr_set) { ao2_unlock(wrapper); ao2_ref(wrapper, -1); return -1; } wrapper->interface->format_attr_set(&format->fattr, ap); ao2_unlock(wrapper); ao2_ref(wrapper, -1); return 0; } struct ast_format *ast_format_append(struct ast_format *format, ... ) { va_list ap; va_start(ap, format); format_set_helper(format, ap); va_end(ap); return format; }