java-topology/docs/tickets/asterisk-0002-confbridge-active-list-user-find-linear.md

2 KiB

asterisk-0002 — app_confbridge: active_list/waiting_list have no channel-name index

Severity: MEDIUM CWE: CWE-407 (Inefficient Algorithmic Complexity) Target: asterisk/asterisk File: apps/app_confbridge.c, apps/confbridge/include/confbridge.h Lines: confbridge.h:260-261, app_confbridge.c:1757, 1768, 3387, 3468, 3687

Description

confbridge_conference stores participants as two plain linked lists:

/* confbridge.h:260-261 */
AST_LIST_HEAD_NOLOCK(, confbridge_user) active_list;
AST_LIST_HEAD_NOLOCK(, confbridge_user) waiting_list;

Every operation that identifies a user by channel name (kick, mute, unmute, video-source selection, AMI/ARI events) traverses the entire list:

/* app_confbridge.c:1757-1776 */
AST_LIST_TRAVERSE(&conference->active_list, user, list) {
    if (strcasecmp(ast_channel_name(user->chan),
                   old_snapshot->base->name) == 0) {
        found_user = 1;
        break;
    }
}
if (!found_user && conference->waitingusers) {
    AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
        if (strcasecmp(ast_channel_name(user->chan), ...) == 0) { ... }
    }
}

There are at least 12 traversal sites in app_confbridge.c. In a conference with P participants each AMI/ARI kick/mute costs O(P). A conference of 500 participants (common for webinar/town-hall use cases) with frequent moderator actions creates quadratic work per conference.

Complexity

  • Before: O(P) per user-by-name lookup across P participants
  • After: O(1) with an ao2_container keyed on channel name

Fix

Add an ao2_container *users_by_name field to confbridge_conference, keyed on ast_channel_name(user->chan). Link/unlink on join/leave. Replace all AST_LIST_TRAVERSE + strcasecmp patterns with a single ao2_find(conference->users_by_name, channel_name, OBJ_SEARCH_KEY).

Patch

defects/asterisk/patch/asterisk-0002.patch

Test

defects/asterisk/unit/AsteriskTest.java — benchmark ASTERISK_CONFBRIDGE_USER_FIND