diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 0574accef8..d4cce4b46c 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -317,14 +317,47 @@ static int execute_menu_entry(struct confbridge_conference *conference, static int conference_bridge_hash_cb(const void *obj, const int flags) { const struct confbridge_conference *conference = obj; - return ast_str_case_hash(conference->name); + const char *name = obj; + int hash; + + switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) { + default: + case OBJ_POINTER: + name = conference->name; + /* Fall through */ + case OBJ_KEY: + hash = ast_str_case_hash(name); + break; + case OBJ_PARTIAL_KEY: + /* Should never happen in hash callback. */ + ast_assert(0); + hash = 0; + break; + } + return hash; } /*! \brief Comparison function used for conference bridges container */ static int conference_bridge_cmp_cb(void *obj, void *arg, int flags) { - const struct confbridge_conference *conference0 = obj, *conference1 = arg; - return (!strcasecmp(conference0->name, conference1->name) ? CMP_MATCH | CMP_STOP : 0); + const struct confbridge_conference *left = obj; + const struct confbridge_conference *right = arg; + const char *right_name = arg; + int cmp; + + switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) { + default: + case OBJ_POINTER: + right_name = right->name; + /* Fall through */ + case OBJ_KEY: + cmp = strcasecmp(left->name, right_name); + break; + case OBJ_PARTIAL_KEY: + cmp = strncasecmp(left->name, right_name, strlen(right_name)); + break; + } + return cmp ? 0 : CMP_MATCH; } const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds) @@ -1233,21 +1266,17 @@ void conf_ended(struct confbridge_conference *conference) */ static struct confbridge_conference *join_conference_bridge(const char *conference_name, struct confbridge_user *user) { - struct confbridge_conference *conference = NULL; + struct confbridge_conference *conference; struct post_join_action *action; - struct confbridge_conference tmp; int max_members_reached = 0; - ast_copy_string(tmp.name, conference_name, sizeof(tmp.name)); - /* We explictly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same */ ao2_lock(conference_bridges); ast_debug(1, "Trying to find conference bridge '%s'\n", conference_name); /* Attempt to find an existing conference bridge */ - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); - + conference = ao2_find(conference_bridges, conference_name, OBJ_KEY); if (conference && conference->b_profile.max_members) { max_members_reached = conference->b_profile.max_members > conference->activeusers ? 0 : 1; } @@ -2225,7 +2254,7 @@ static int kick_conference_participant(struct confbridge_conference *conference, static char *complete_confbridge_name(const char *line, const char *word, int pos, int state) { int which = 0; - struct confbridge_conference *conference = NULL; + struct confbridge_conference *conference; char *res = NULL; int wordlen = strlen(word); struct ao2_iterator iter; @@ -2244,17 +2273,15 @@ static char *complete_confbridge_name(const char *line, const char *word, int po return res; } -static char *complete_confbridge_participant(const char *bridge_name, const char *line, const char *word, int pos, int state) +static char *complete_confbridge_participant(const char *conference_name, const char *line, const char *word, int pos, int state) { int which = 0; RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup); - struct confbridge_conference tmp; struct confbridge_user *user; char *res = NULL; int wordlen = strlen(word); - ast_copy_string(tmp.name, bridge_name, sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, conference_name, OBJ_KEY); if (!conference) { return NULL; } @@ -2280,8 +2307,7 @@ static char *complete_confbridge_participant(const char *bridge_name, const char static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - struct confbridge_conference *conference = NULL; - struct confbridge_conference tmp; + struct confbridge_conference *conference; switch (cmd) { case CLI_INIT: @@ -2304,8 +2330,7 @@ static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct return CLI_SHOWUSAGE; } - ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY); if (!conference) { ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]); return CLI_SUCCESS; @@ -2395,10 +2420,8 @@ static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct if (a->argc == 3) { struct confbridge_user *user; - struct confbridge_conference tmp; - ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY); if (!conference) { ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]); return CLI_SUCCESS; @@ -2428,12 +2451,10 @@ static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct */ static int generic_lock_unlock_helper(int lock, const char *conference_name) { - struct confbridge_conference *conference = NULL; - struct confbridge_conference tmp; + struct confbridge_conference *conference; int res = 0; - ast_copy_string(tmp.name, conference_name, sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, conference_name, OBJ_KEY); if (!conference) { return -1; } @@ -2455,12 +2476,11 @@ static int generic_lock_unlock_helper(int lock, const char *conference_name) */ static int generic_mute_unmute_helper(int mute, const char *conference_name, const char *chan_name) { - struct confbridge_conference *conference = NULL; - struct confbridge_conference tmp; - struct confbridge_user *user = NULL; + struct confbridge_conference *conference; + struct confbridge_user *user; int res = 0; - ast_copy_string(tmp.name, conference_name, sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + + conference = ao2_find(conference_bridges, conference_name, OBJ_KEY); if (!conference) { return -1; } @@ -2607,8 +2627,7 @@ static char *handle_cli_confbridge_unlock(struct ast_cli_entry *e, int cmd, stru static char *handle_cli_confbridge_start_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { const char *rec_file = NULL; - struct confbridge_conference *conference = NULL; - struct confbridge_conference tmp; + struct confbridge_conference *conference; switch (cmd) { case CLI_INIT: @@ -2633,8 +2652,7 @@ static char *handle_cli_confbridge_start_record(struct ast_cli_entry *e, int cmd rec_file = a->argv[4]; } - ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY); if (!conference) { ast_cli(a->fd, "Conference not found.\n"); return CLI_FAILURE; @@ -2665,8 +2683,7 @@ static char *handle_cli_confbridge_start_record(struct ast_cli_entry *e, int cmd static char *handle_cli_confbridge_stop_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - struct confbridge_conference *conference = NULL; - struct confbridge_conference tmp; + struct confbridge_conference *conference; int ret; switch (cmd) { @@ -2686,8 +2703,7 @@ static char *handle_cli_confbridge_stop_record(struct ast_cli_entry *e, int cmd, return CLI_SHOWUSAGE; } - ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY); if (!conference) { ast_cli(a->fd, "Conference not found.\n"); return CLI_SUCCESS; @@ -2754,7 +2770,6 @@ static int action_confbridgelist(struct mansession *s, const struct message *m) const char *conference_name = astman_get_header(m, "Conference"); struct confbridge_user *user; struct confbridge_conference *conference; - struct confbridge_conference tmp; char id_text[80]; int total = 0; @@ -2770,8 +2785,7 @@ static int action_confbridgelist(struct mansession *s, const struct message *m) astman_send_error(s, m, "No active conferences."); return 0; } - ast_copy_string(tmp.name, conference_name, sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, conference_name, OBJ_KEY); if (!conference) { astman_send_error(s, m, "No Conference by that name found."); return 0; @@ -2804,7 +2818,7 @@ static int action_confbridgelist(struct mansession *s, const struct message *m) static int action_confbridgelistrooms(struct mansession *s, const struct message *m) { const char *actionid = astman_get_header(m, "ActionID"); - struct confbridge_conference *conference = NULL; + struct confbridge_conference *conference; struct ao2_iterator iter; char id_text[512] = ""; int totalitems = 0; @@ -2930,8 +2944,7 @@ static int action_confbridgekick(struct mansession *s, const struct message *m) { const char *conference_name = astman_get_header(m, "Conference"); const char *channel = astman_get_header(m, "Channel"); - struct confbridge_conference *conference = NULL; - struct confbridge_conference tmp; + struct confbridge_conference *conference; int found = 0; if (ast_strlen_zero(conference_name)) { @@ -2943,8 +2956,7 @@ static int action_confbridgekick(struct mansession *s, const struct message *m) return 0; } - ast_copy_string(tmp.name, conference_name, sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, conference_name, OBJ_KEY); if (!conference) { astman_send_error(s, m, "No Conference by that name found."); return 0; @@ -2965,8 +2977,7 @@ static int action_confbridgestartrecord(struct mansession *s, const struct messa { const char *conference_name = astman_get_header(m, "Conference"); const char *recordfile = astman_get_header(m, "RecordFile"); - struct confbridge_conference *conference = NULL; - struct confbridge_conference tmp; + struct confbridge_conference *conference; if (ast_strlen_zero(conference_name)) { astman_send_error(s, m, "No Conference name provided."); @@ -2977,8 +2988,7 @@ static int action_confbridgestartrecord(struct mansession *s, const struct messa return 0; } - ast_copy_string(tmp.name, conference_name, sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, conference_name, OBJ_KEY); if (!conference) { astman_send_error(s, m, "No Conference by that name found."); return 0; @@ -3011,8 +3021,7 @@ static int action_confbridgestartrecord(struct mansession *s, const struct messa static int action_confbridgestoprecord(struct mansession *s, const struct message *m) { const char *conference_name = astman_get_header(m, "Conference"); - struct confbridge_conference *conference = NULL; - struct confbridge_conference tmp; + struct confbridge_conference *conference; if (ast_strlen_zero(conference_name)) { astman_send_error(s, m, "No Conference name provided."); @@ -3023,8 +3032,7 @@ static int action_confbridgestoprecord(struct mansession *s, const struct messag return 0; } - ast_copy_string(tmp.name, conference_name, sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, conference_name, OBJ_KEY); if (!conference) { astman_send_error(s, m, "No Conference by that name found."); return 0; @@ -3048,9 +3056,8 @@ static int action_confbridgesetsinglevideosrc(struct mansession *s, const struct { const char *conference_name = astman_get_header(m, "Conference"); const char *channel = astman_get_header(m, "Channel"); - struct confbridge_user *user = NULL; - struct confbridge_conference *conference = NULL; - struct confbridge_conference tmp; + struct confbridge_user *user; + struct confbridge_conference *conference; if (ast_strlen_zero(conference_name)) { astman_send_error(s, m, "No Conference name provided."); @@ -3065,8 +3072,7 @@ static int action_confbridgesetsinglevideosrc(struct mansession *s, const struct return 0; } - ast_copy_string(tmp.name, conference_name, sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, conference_name, OBJ_KEY); if (!conference) { astman_send_error(s, m, "No Conference by that name found."); return 0; @@ -3095,10 +3101,9 @@ static int action_confbridgesetsinglevideosrc(struct mansession *s, const struct static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { - char *parse = NULL; - struct confbridge_conference *conference = NULL; - struct confbridge_user *user = NULL; - struct confbridge_conference tmp; + char *parse; + struct confbridge_conference *conference; + struct confbridge_user *user; int count = 0; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(type); @@ -3114,12 +3119,7 @@ static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) { return -1; } - if (!ao2_container_count(conference_bridges)) { - snprintf(buf, len, "0"); - return 0; - } - ast_copy_string(tmp.name, args.confno, sizeof(tmp.name)); - conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + conference = ao2_find(conference_bridges, args.confno, OBJ_KEY); if (!conference) { snprintf(buf, len, "0"); return 0; @@ -3210,33 +3210,34 @@ void conf_remove_user_waiting(struct confbridge_conference *conference, struct c /*! \brief Called when module is being unloaded */ static int unload_module(void) { - int res = ast_unregister_application(app); + ast_unregister_application(app); ast_custom_function_unregister(&confbridge_function); ast_custom_function_unregister(&confbridge_info_function); - ast_cli_unregister_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry)); + ast_cli_unregister_multiple(cli_confbridge, ARRAY_LEN(cli_confbridge)); + + ast_manager_unregister("ConfbridgeList"); + ast_manager_unregister("ConfbridgeListRooms"); + ast_manager_unregister("ConfbridgeMute"); + ast_manager_unregister("ConfbridgeUnmute"); + ast_manager_unregister("ConfbridgeKick"); + ast_manager_unregister("ConfbridgeUnlock"); + ast_manager_unregister("ConfbridgeLock"); + ast_manager_unregister("ConfbridgeStartRecord"); + ast_manager_unregister("ConfbridgeStopRecord"); + ast_manager_unregister("ConfbridgeSetSingleVideoSrc"); /* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */ - ao2_ref(conference_bridges, -1); + ao2_cleanup(conference_bridges); + conference_bridges = NULL; conf_destroy_config(); ast_channel_unregister(&record_tech); record_tech.capabilities = ast_format_cap_destroy(record_tech.capabilities); - res |= ast_manager_unregister("ConfbridgeList"); - res |= ast_manager_unregister("ConfbridgeListRooms"); - res |= ast_manager_unregister("ConfbridgeMute"); - res |= ast_manager_unregister("ConfbridgeUnmute"); - res |= ast_manager_unregister("ConfbridgeKick"); - res |= ast_manager_unregister("ConfbridgeUnlock"); - res |= ast_manager_unregister("ConfbridgeLock"); - res |= ast_manager_unregister("ConfbridgeStartRecord"); - res |= ast_manager_unregister("ConfbridgeStopRecord"); - res |= ast_manager_unregister("ConfbridgeSetSingleVideoSrc"); - - return res; + return 0; } /*! @@ -3257,30 +3258,33 @@ static int load_module(void) ast_log(LOG_ERROR, "Unable to load config. Not loading module.\n"); return AST_MODULE_LOAD_DECLINE; } - if ((ast_custom_function_register(&confbridge_function))) { - return AST_MODULE_LOAD_FAILURE; - } - if ((ast_custom_function_register(&confbridge_info_function))) { - return AST_MODULE_LOAD_FAILURE; - } + if (!(record_tech.capabilities = ast_format_cap_alloc())) { + unload_module(); return AST_MODULE_LOAD_FAILURE; } ast_format_cap_add_all(record_tech.capabilities); if (ast_channel_register(&record_tech)) { ast_log(LOG_ERROR, "Unable to register ConfBridge recorder.\n"); + unload_module(); return AST_MODULE_LOAD_FAILURE; } + /* Create a container to hold the conference bridges */ - if (!(conference_bridges = ao2_container_alloc(CONFERENCE_BRIDGE_BUCKETS, conference_bridge_hash_cb, conference_bridge_cmp_cb))) { - return AST_MODULE_LOAD_FAILURE; - } - if (ast_register_application_xml(app, confbridge_exec)) { - ao2_ref(conference_bridges, -1); + conference_bridges = ao2_container_alloc(CONFERENCE_BRIDGE_BUCKETS, + conference_bridge_hash_cb, conference_bridge_cmp_cb); + if (!conference_bridges) { + unload_module(); return AST_MODULE_LOAD_FAILURE; } - res |= ast_cli_register_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry)); + res |= ast_register_application_xml(app, confbridge_exec); + + res |= ast_custom_function_register(&confbridge_function); + res |= ast_custom_function_register(&confbridge_info_function); + + res |= ast_cli_register_multiple(cli_confbridge, ARRAY_LEN(cli_confbridge)); + res |= ast_manager_register_xml("ConfbridgeList", EVENT_FLAG_REPORTING, action_confbridgelist); res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms); res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute); @@ -3292,6 +3296,7 @@ static int load_module(void) res |= ast_manager_register_xml("ConfbridgeStopRecord", EVENT_FLAG_CALL, action_confbridgestoprecord); res |= ast_manager_register_xml("ConfbridgeSetSingleVideoSrc", EVENT_FLAG_CALL, action_confbridgesetsinglevideosrc); if (res) { + unload_module(); return AST_MODULE_LOAD_FAILURE; } diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c index 83184d10a5..3c130e92e4 100644 --- a/apps/confbridge/conf_config_parser.c +++ b/apps/confbridge/conf_config_parser.c @@ -648,32 +648,95 @@ CONFIG_INFO_STANDARD(cfg_info, cfg_handle, confbridge_cfg_alloc, /*! bridge profile container functions */ static int bridge_cmp_cb(void *obj, void *arg, int flags) { - const struct bridge_profile *entry1 = obj, *entry2 = arg; - const char *name = arg; - return (!strcasecmp(entry1->name, flags & OBJ_KEY ? name : entry2->name)) ? - CMP_MATCH | CMP_STOP : 0; + const struct bridge_profile *left = obj; + const struct bridge_profile *right = arg; + const char *right_name = arg; + int cmp; + + switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) { + default: + case OBJ_POINTER: + right_name = right->name; + /* Fall through */ + case OBJ_KEY: + cmp = strcasecmp(left->name, right_name); + break; + case OBJ_PARTIAL_KEY: + cmp = strncasecmp(left->name, right_name, strlen(right_name)); + break; + } + return cmp ? 0 : CMP_MATCH; } + static int bridge_hash_cb(const void *obj, const int flags) { const struct bridge_profile *b_profile = obj; const char *name = obj; - return ast_str_case_hash(flags & OBJ_KEY ? name : b_profile->name); + int hash; + + switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) { + default: + case OBJ_POINTER: + name = b_profile->name; + /* Fall through */ + case OBJ_KEY: + hash = ast_str_case_hash(name); + break; + case OBJ_PARTIAL_KEY: + /* Should never happen in hash callback. */ + ast_assert(0); + hash = 0; + break; + } + return hash; } /*! menu container functions */ static int menu_cmp_cb(void *obj, void *arg, int flags) { - const struct conf_menu *entry1 = obj, *entry2 = arg; - const char *name = arg; - return (!strcasecmp(entry1->name, flags & OBJ_KEY ? name : entry2->name)) ? - CMP_MATCH | CMP_STOP : 0; + const struct conf_menu *left = obj; + const struct conf_menu *right = arg; + const char *right_name = arg; + int cmp; + + switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) { + default: + case OBJ_POINTER: + right_name = right->name; + /* Fall through */ + case OBJ_KEY: + cmp = strcasecmp(left->name, right_name); + break; + case OBJ_PARTIAL_KEY: + cmp = strncasecmp(left->name, right_name, strlen(right_name)); + break; + } + return cmp ? 0 : CMP_MATCH; } + static int menu_hash_cb(const void *obj, const int flags) { const struct conf_menu *menu = obj; const char *name = obj; - return ast_str_case_hash(flags & OBJ_KEY ? name : menu->name); + int hash; + + switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) { + default: + case OBJ_POINTER: + name = menu->name; + /* Fall through */ + case OBJ_KEY: + hash = ast_str_case_hash(name); + break; + case OBJ_PARTIAL_KEY: + /* Should never happen in hash callback. */ + ast_assert(0); + hash = 0; + break; + } + return hash; } + static void menu_destructor(void *obj) { struct conf_menu *menu = obj; @@ -688,16 +751,47 @@ static void menu_destructor(void *obj) /*! User profile container functions */ static int user_cmp_cb(void *obj, void *arg, int flags) { - const struct user_profile *entry1 = obj, *entry2 = arg; - const char *name = arg; - return (!strcasecmp(entry1->name, flags & OBJ_KEY ? name : entry2->name)) ? - CMP_MATCH | CMP_STOP : 0; + const struct user_profile *left = obj; + const struct user_profile *right = arg; + const char *right_name = arg; + int cmp; + + switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) { + default: + case OBJ_POINTER: + right_name = right->name; + /* Fall through */ + case OBJ_KEY: + cmp = strcasecmp(left->name, right_name); + break; + case OBJ_PARTIAL_KEY: + cmp = strncasecmp(left->name, right_name, strlen(right_name)); + break; + } + return cmp ? 0 : CMP_MATCH; } + static int user_hash_cb(const void *obj, const int flags) { const struct user_profile *u_profile = obj; const char *name = obj; - return ast_str_case_hash(flags & OBJ_KEY ? name : u_profile->name); + int hash; + + switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) { + default: + case OBJ_POINTER: + name = u_profile->name; + /* Fall through */ + case OBJ_KEY: + hash = ast_str_case_hash(name); + break; + case OBJ_PARTIAL_KEY: + /* Should never happen in hash callback. */ + ast_assert(0); + hash = 0; + break; + } + return hash; } /*! Bridge Profile Sounds functions */