summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_minivm.c8
-rw-r--r--apps/app_voicemail.c6
-rw-r--r--apps/confbridge/conf_config_parser.c12
-rw-r--r--channels/chan_alsa.c20
-rw-r--r--channels/chan_sip.c27
-rw-r--r--channels/chan_skinny.c40
-rw-r--r--funcs/func_odbc.c6
-rw-r--r--main/astmm.c21
-rw-r--r--main/bridge.c14
-rw-r--r--main/ccss.c9
-rw-r--r--main/channel.c6
-rw-r--r--main/cli.c33
-rw-r--r--main/iostream.c6
-rw-r--r--main/libasteriskssl.c11
-rw-r--r--main/pbx_app.c3
-rw-r--r--main/pbx_hangup_handler.c2
-rw-r--r--main/stream.c13
-rw-r--r--main/tcptls.c4
-rw-r--r--res/res_sorcery_memory_cache.c14
-rw-r--r--tests/test_stream.c400
20 files changed, 547 insertions, 108 deletions
diff --git a/apps/app_minivm.c b/apps/app_minivm.c
index a060ad183..4cc2f4796 100644
--- a/apps/app_minivm.c
+++ b/apps/app_minivm.c
@@ -3014,11 +3014,9 @@ static char *complete_minivm_show_users(const char *line, const char *word, int
struct minivm_account *vmu;
const char *domain = "";
- /* 0 - voicemail; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
+ /* 0 - minivm; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
if (pos > 4)
return NULL;
- if (pos == 3)
- return (state == 0) ? ast_strdup("for") : NULL;
wordlen = strlen(word);
AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
if (!strncasecmp(word, vmu->domain, wordlen)) {
@@ -3040,9 +3038,9 @@ static char *handle_minivm_show_users(struct ast_cli_entry *e, int cmd, struct a
switch (cmd) {
case CLI_INIT:
- e->command = "minivm list accounts";
+ e->command = "minivm list accounts [for]";
e->usage =
- "Usage: minivm list accounts\n"
+ "Usage: minivm list accounts [for <domain>]\n"
" Lists all mailboxes currently set up\n";
return NULL;
case CLI_GENERATE:
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 37f8aa96f..3016f65ba 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -12745,11 +12745,9 @@ static char *complete_voicemail_show_users(const char *line, const char *word, i
struct ast_vm_user *vmu;
const char *context = "";
- /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
+ /* 0 - voicemail; 1 - show; 2 - users; 3 - for; 4 - <context> */
if (pos > 4)
return NULL;
- if (pos == 3)
- return (state == 0) ? ast_strdup("for") : NULL;
wordlen = strlen(word);
AST_LIST_TRAVERSE(&users, vmu, list) {
if (!strncasecmp(word, vmu->context, wordlen)) {
@@ -12772,7 +12770,7 @@ static char *handle_voicemail_show_users(struct ast_cli_entry *e, int cmd, struc
switch (cmd) {
case CLI_INIT:
- e->command = "voicemail show users";
+ e->command = "voicemail show users [for]";
e->usage =
"Usage: voicemail show users [for <context>]\n"
" Lists all mailboxes currently set up\n";
diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c
index 1749b585e..29d7b7f53 100644
--- a/apps/confbridge/conf_config_parser.c
+++ b/apps/confbridge/conf_config_parser.c
@@ -1371,7 +1371,7 @@ static char *handle_cli_confbridge_show_user_profiles(struct ast_cli_entry *e, i
case CLI_INIT:
e->command = "confbridge show profile users";
e->usage =
- "Usage confbridge show profile users\n";
+ "Usage: confbridge show profile users\n";
return NULL;
case CLI_GENERATE:
return NULL;
@@ -1401,7 +1401,7 @@ static char *handle_cli_confbridge_show_user_profile(struct ast_cli_entry *e, in
case CLI_INIT:
e->command = "confbridge show profile user";
e->usage =
- "Usage confbridge show profile user [<profile name>]\n";
+ "Usage: confbridge show profile user [<profile name>]\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 4) {
@@ -1522,7 +1522,7 @@ static char *handle_cli_confbridge_show_bridge_profiles(struct ast_cli_entry *e,
case CLI_INIT:
e->command = "confbridge show profile bridges";
e->usage =
- "Usage confbridge show profile bridges\n";
+ "Usage: confbridge show profile bridges\n";
return NULL;
case CLI_GENERATE:
return NULL;
@@ -1554,7 +1554,7 @@ static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e,
case CLI_INIT:
e->command = "confbridge show profile bridge";
e->usage =
- "Usage confbridge show profile bridge <profile name>\n";
+ "Usage: confbridge show profile bridge <profile name>\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 4) {
@@ -1706,7 +1706,7 @@ static char *handle_cli_confbridge_show_menus(struct ast_cli_entry *e, int cmd,
case CLI_INIT:
e->command = "confbridge show menus";
e->usage =
- "Usage confbridge show profile menus\n";
+ "Usage: confbridge show profile menus\n";
return NULL;
case CLI_GENERATE:
return NULL;
@@ -1740,7 +1740,7 @@ static char *handle_cli_confbridge_show_menu(struct ast_cli_entry *e, int cmd, s
case CLI_INIT:
e->command = "confbridge show menu";
e->usage =
- "Usage confbridge show menu [<menu name>]\n";
+ "Usage: confbridge show menu [<menu name>]\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 3) {
diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c
index d09dc1c53..c50b5408e 100644
--- a/channels/chan_alsa.c
+++ b/channels/chan_alsa.c
@@ -637,29 +637,13 @@ static struct ast_channel *alsa_request(const char *type, struct ast_format_cap
return tmp;
}
-static char *autoanswer_complete(const char *line, const char *word, int pos, int state)
-{
- switch (state) {
- case 0:
- if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2)))
- return ast_strdup("on");
- case 1:
- if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3)))
- return ast_strdup("off");
- default:
- return NULL;
- }
-
- return NULL;
-}
-
static char *console_autoanswer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char *res = CLI_SUCCESS;
switch (cmd) {
case CLI_INIT:
- e->command = "console autoanswer";
+ e->command = "console autoanswer [on|off]";
e->usage =
"Usage: console autoanswer [on|off]\n"
" Enables or disables autoanswer feature. If used without\n"
@@ -667,7 +651,7 @@ static char *console_autoanswer(struct ast_cli_entry *e, int cmd, struct ast_cli
" The default value of autoanswer is in 'alsa.conf'.\n";
return NULL;
case CLI_GENERATE:
- return autoanswer_complete(a->line, a->word, a->pos, a->n);
+ return NULL;
}
if ((a->argc != 2) && (a->argc != 3))
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 5da134086..3e4dafb1b 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -19587,7 +19587,7 @@ static char *sip_show_inuse(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
switch (cmd) {
case CLI_INIT:
- e->command = "sip show inuse";
+ e->command = "sip show inuse [all]";
e->usage =
"Usage: sip show inuse [all]\n"
" List all SIP devices usage counters and limits.\n"
@@ -19777,7 +19777,7 @@ static char *sip_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
switch (cmd) {
case CLI_INIT:
- e->command = "sip show users";
+ e->command = "sip show users [like]";
e->usage =
"Usage: sip show users [like <pattern>]\n"
" Lists all known SIP users.\n"
@@ -19916,7 +19916,7 @@ static char *sip_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
{
switch (cmd) {
case CLI_INIT:
- e->command = "sip show peers";
+ e->command = "sip show peers [like]";
e->usage =
"Usage: sip show peers [like <pattern>]\n"
" Lists all known SIP peers.\n"
@@ -20630,7 +20630,12 @@ static char *sip_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args
" Option \"load\" forces lookup of peer in realtime storage.\n";
return NULL;
case CLI_GENERATE:
- return complete_sip_show_peer(a->line, a->word, a->pos, a->n);
+ if (a->pos == 4) {
+ static const char * const completions[] = { "load", NULL };
+ return ast_cli_complete(a->word, completions, a->n);
+ } else {
+ return complete_sip_show_peer(a->line, a->word, a->pos, a->n);
+ }
}
return _sip_show_peer(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv);
}
@@ -20800,7 +20805,12 @@ static char *sip_qualify_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_a
" Option \"load\" forces lookup of peer in realtime storage.\n";
return NULL;
case CLI_GENERATE:
- return complete_sip_show_peer(a->line, a->word, a->pos, a->n);
+ if (a->pos == 4) {
+ static const char * const completions[] = { "load", NULL };
+ return ast_cli_complete(a->word, completions, a->n);
+ } else {
+ return complete_sip_show_peer(a->line, a->word, a->pos, a->n);
+ }
}
return _sip_qualify_peer(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv);
}
@@ -21171,7 +21181,12 @@ static char *sip_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args
" Option \"load\" forces lookup of peer in realtime storage.\n";
return NULL;
case CLI_GENERATE:
- return complete_sip_show_user(a->line, a->word, a->pos, a->n);
+ if (a->pos == 4) {
+ static const char * const completions[] = { "load", NULL };
+ return ast_cli_complete(a->word, completions, a->n);
+ } else {
+ return complete_sip_show_user(a->line, a->word, a->pos, a->n);
+ }
}
if (a->argc < 4)
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 0ef016635..a3a2f87fb 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -3921,24 +3921,40 @@ static char *complete_skinny_show_device(const char *line, const char *word, int
static char *complete_skinny_reset(const char *line, const char *word, int pos, int state)
{
- return (pos == 2 ? complete_skinny_devices(word, state) : NULL);
+ if (pos == 2) {
+ static const char * const completions[] = { "all", NULL };
+ char *ret = ast_cli_complete(word, completions, state);
+ if (!ret) {
+ ret = complete_skinny_devices(word, state - 1);
+ }
+ return ret;
+ } else if (pos == 3) {
+ static const char * const completions[] = { "restart", NULL };
+ return ast_cli_complete(word, completions, state);
+ }
+
+ return NULL;
}
static char *complete_skinny_show_line(const char *line, const char *word, int pos, int state)
{
- struct skinny_device *d;
- struct skinny_line *l;
- int wordlen = strlen(word), which = 0;
+ if (pos == 3) {
+ struct skinny_device *d;
+ struct skinny_line *l;
+ int wordlen = strlen(word), which = 0;
- if (pos != 3)
- return NULL;
-
- AST_LIST_TRAVERSE(&devices, d, list) {
- AST_LIST_TRAVERSE(&d->lines, l, list) {
- if (!strncasecmp(word, l->name, wordlen) && ++which > state) {
- return ast_strdup(l->name);
+ AST_LIST_TRAVERSE(&devices, d, list) {
+ AST_LIST_TRAVERSE(&d->lines, l, list) {
+ if (!strncasecmp(word, l->name, wordlen) && ++which > state) {
+ return ast_strdup(l->name);
+ }
}
}
+ } else if (pos == 4) {
+ static const char * const completions[] = { "on", NULL };
+ return ast_cli_complete(word, completions, state);
+ } else if (pos == 5) {
+ return complete_skinny_devices(word, state);
}
return NULL;
@@ -4580,7 +4596,7 @@ static char *handle_skinny_show_line(struct ast_cli_entry *e, int cmd, struct as
case CLI_INIT:
e->command = "skinny show line";
e->usage =
- "Usage: skinny show line <Line> [ on <DeviceID|DeviceName> ]\n"
+ "Usage: skinny show line <Line> [on <DeviceID|DeviceName>]\n"
" List all lineinformation of a specific line known to the Skinny subsystem.\n";
return NULL;
case CLI_GENERATE:
diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c
index e014b633c..06e4a6ada 100644
--- a/funcs/func_odbc.c
+++ b/funcs/func_odbc.c
@@ -1417,7 +1417,8 @@ static char *cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args
AST_RWLIST_UNLOCK(&queries);
return NULL;
} else if (a->pos == 4) {
- return a->n == 0 ? ast_strdup("exec") : NULL;
+ static const char * const completions[] = { "exec", NULL };
+ return ast_cli_complete(a->word, completions, a->n);
} else {
return NULL;
}
@@ -1623,7 +1624,8 @@ static char *cli_odbc_write(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
AST_RWLIST_UNLOCK(&queries);
return NULL;
} else if (a->pos == 5) {
- return a->n == 0 ? ast_strdup("exec") : NULL;
+ static const char * const completions[] = { "exec", NULL };
+ return ast_cli_complete(a->word, completions, a->n);
} else {
return NULL;
}
diff --git a/main/astmm.c b/main/astmm.c
index 0ad29a6fb..9c26f0fa7 100644
--- a/main/astmm.c
+++ b/main/astmm.c
@@ -691,17 +691,12 @@ static char *handle_memory_atexit_list(struct ast_cli_entry *e, int cmd, struct
{
switch (cmd) {
case CLI_INIT:
- e->command = "memory atexit list";
+ e->command = "memory atexit list {on|off}";
e->usage =
"Usage: memory atexit list {on|off}\n"
" Enable dumping a list of still allocated memory segments at exit.\n";
return NULL;
case CLI_GENERATE:
- if (a->pos == 3) {
- const char * const options[] = { "off", "on", NULL };
-
- return ast_cli_complete(a->word, options, a->n);
- }
return NULL;
}
@@ -728,7 +723,7 @@ static char *handle_memory_atexit_summary(struct ast_cli_entry *e, int cmd, stru
switch (cmd) {
case CLI_INIT:
- e->command = "memory atexit summary";
+ e->command = "memory atexit summary {off|byline|byfunc|byfile}";
e->usage =
"Usage: memory atexit summary {off|byline|byfunc|byfile}\n"
" Summary of still allocated memory segments at exit options.\n"
@@ -740,11 +735,6 @@ static char *handle_memory_atexit_summary(struct ast_cli_entry *e, int cmd, stru
" Note: byline, byfunc, and byfile are cumulative enables.\n";
return NULL;
case CLI_GENERATE:
- if (a->pos == 3) {
- const char * const options[] = { "off", "byline", "byfunc", "byfile", NULL };
-
- return ast_cli_complete(a->word, options, a->n);
- }
return NULL;
}
@@ -1043,7 +1033,7 @@ static char *handle_memory_backtrace(struct ast_cli_entry *e, int cmd, struct as
{
switch (cmd) {
case CLI_INIT:
- e->command = "memory backtrace";
+ e->command = "memory backtrace {on|off}";
e->usage =
"Usage: memory backtrace {on|off}\n"
" Enable dumping an allocation backtrace with memory diagnostics.\n"
@@ -1051,11 +1041,6 @@ static char *handle_memory_backtrace(struct ast_cli_entry *e, int cmd, struct as
" can be CPU intensive.\n";
return NULL;
case CLI_GENERATE:
- if (a->pos == 2) {
- const char * const options[] = { "off", "on", NULL };
-
- return ast_cli_complete(a->word, options, a->n);
- }
return NULL;
}
diff --git a/main/bridge.c b/main/bridge.c
index 13c01fa27..b6ba0a2bf 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -5170,12 +5170,6 @@ static char *complete_bridge_participant(const char *bridge_name, const char *li
return NULL;
}
- if (!state) {
- ao2_ref(bridge, -1);
- return ast_strdup("all");
- }
- state--;
-
{
SCOPED_LOCK(bridge_lock, bridge, ast_bridge_lock, ast_bridge_unlock);
@@ -5197,6 +5191,8 @@ static char *complete_bridge_participant(const char *bridge_name, const char *li
static char *handle_bridge_kick_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
+ static const char * const completions[] = { "all", NULL };
+ char *complete;
struct ast_bridge *bridge;
switch (cmd) {
@@ -5213,7 +5209,11 @@ static char *handle_bridge_kick_channel(struct ast_cli_entry *e, int cmd, struct
return complete_bridge_live(a->word, a->n);
}
if (a->pos == 3) {
- return complete_bridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
+ complete = ast_cli_complete(a->word, completions, a->n);
+ if (!complete) {
+ complete = complete_bridge_participant(a->argv[2], a->line, a->word, a->pos, a->n - 1);
+ }
+ return complete;
}
return NULL;
}
diff --git a/main/ccss.c b/main/ccss.c
index 6c3e6cbee..f96d7aa1d 100644
--- a/main/ccss.c
+++ b/main/ccss.c
@@ -4566,11 +4566,9 @@ static char *complete_core_id(const char *line, const char *word, int pos, int s
static char *handle_cc_kill(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- static const char * const option[] = { "core", "all", NULL };
-
switch (cmd) {
case CLI_INIT:
- e->command = "cc cancel";
+ e->command = "cc cancel [core|all]";
e->usage =
"Usage: cc cancel can be used in two ways.\n"
" 1. 'cc cancel core [core ID]' will cancel the CC transaction with\n"
@@ -4578,10 +4576,7 @@ static char *handle_cc_kill(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
" 2. 'cc cancel all' will cancel all active CC transactions.\n";
return NULL;
case CLI_GENERATE:
- if (a->pos == 2) {
- return ast_cli_complete(a->word, option, a->n);
- }
- if (a->pos == 3) {
+ if (a->pos == 3 && !strcasecmp(a->argv[2], "core")) {
return complete_core_id(a->line, a->word, a->pos, a->n);
}
return NULL;
diff --git a/main/channel.c b/main/channel.c
index 992c94086..54db47351 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -3133,7 +3133,9 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
fdmap[max].chan = x; /* channel x is linked to this pfds */
max += ast_add_fd(&pfds[max], ast_channel_fd(c[x], y));
}
+ ast_channel_lock(c[x]);
CHECK_BLOCKING(c[x]);
+ ast_channel_unlock(c[x]);
}
/* Add the individual fds */
for (x = 0; x < nfds; x++) {
@@ -3160,7 +3162,9 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
res = ast_poll(pfds, max, rms);
}
for (x = 0; x < n; x++) {
+ ast_channel_lock(c[x]);
ast_clear_flag(ast_channel_flags(c[x]), AST_FLAG_BLOCKING);
+ ast_channel_unlock(c[x]);
}
if (res < 0) { /* Simulate a timeout if we were interrupted */
if (errno != EINTR) {
@@ -3196,12 +3200,14 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
}
if (fdmap[x].chan >= 0) { /* this is a channel */
winner = c[fdmap[x].chan]; /* override previous winners */
+ ast_channel_lock(winner);
if (res & POLLPRI) {
ast_set_flag(ast_channel_flags(winner), AST_FLAG_EXCEPTION);
} else {
ast_clear_flag(ast_channel_flags(winner), AST_FLAG_EXCEPTION);
}
ast_channel_fdno_set(winner, fdmap[x].fdno);
+ ast_channel_unlock(winner);
} else { /* this is an fd */
if (outfd) {
*outfd = pfds[x].fd;
diff --git a/main/cli.c b/main/cli.c
index 632883d39..ccdbb97c3 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -916,6 +916,7 @@ static char *handle_modlist(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
static char *handle_showcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
+ static const char * const completions[] = { "seconds", NULL };
struct timeval curtime = ast_tvnow();
int showuptime, printsec;
@@ -923,7 +924,7 @@ static char *handle_showcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_a
case CLI_INIT:
e->command = "core show calls [uptime]";
e->usage =
- "Usage: core show calls [uptime] [seconds]\n"
+ "Usage: core show calls [uptime [seconds]]\n"
" Lists number of currently active calls and total number of calls\n"
" processed through PBX since last restart. If 'uptime' is specified\n"
" the system uptime is also displayed. If 'seconds' is specified in\n"
@@ -933,7 +934,7 @@ static char *handle_showcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_a
case CLI_GENERATE:
if (a->pos != e->args)
return NULL;
- return a->n == 0 ? ast_strdup("seconds") : NULL;
+ return ast_cli_complete(a->word, completions, a->n);
}
/* regular handler */
@@ -1103,7 +1104,9 @@ static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
static char *handle_softhangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- struct ast_channel *c=NULL;
+ struct ast_channel *c = NULL;
+ static const char * const completions[] = { "all", NULL };
+ char *complete;
switch (cmd) {
case CLI_INIT:
@@ -1116,7 +1119,14 @@ static char *handle_softhangup(struct ast_cli_entry *e, int cmd, struct ast_cli_
" will see the hangup request.\n";
return NULL;
case CLI_GENERATE:
- return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
+ if (a->pos != e->args) {
+ return NULL;
+ }
+ complete = ast_cli_complete(a->word, completions, a->n);
+ if (!complete) {
+ complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
+ }
+ return complete;
}
if (a->argc != 4) {
@@ -1428,6 +1438,8 @@ static int channel_set_debug(void *obj, void *arg, void *data, int flags)
static char *handle_core_set_debug_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct ast_channel *c = NULL;
+ static const char * const completions_all[] = { "all", NULL };
+ static const char * const completions_off[] = { "off", NULL };
struct channel_set_debug_args args = {
.fd = a->fd,
};
@@ -1440,10 +1452,15 @@ static char *handle_core_set_debug_channel(struct ast_cli_entry *e, int cmd, str
" Enables/disables debugging on all or on a specific channel.\n";
return NULL;
case CLI_GENERATE:
- /* XXX remember to handle the optional "off" */
- if (a->pos != e->args)
- return NULL;
- return a->n == 0 ? ast_strdup("all") : ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
+ if (a->pos == 4) {
+ char *complete = ast_cli_complete(a->word, completions_all, a->n);
+ if (!complete) {
+ complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
+ }
+ return complete;
+ } else if (a->pos == 5) {
+ return ast_cli_complete(a->word, completions_off, a->n);
+ }
}
if (cmd == (CLI_HANDLER + 1000)) {
diff --git a/main/iostream.c b/main/iostream.c
index 22cd5985c..6187bc2fb 100644
--- a/main/iostream.c
+++ b/main/iostream.c
@@ -465,19 +465,19 @@ int ast_iostream_close(struct ast_iostream *stream)
SSL_get_error(stream->ssl, res));
}
-#if defined(OPENSSL_API_COMPAT) && OPENSSL_API_COMPAT >= 0x10100000L
+#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
if (!SSL_is_server(stream->ssl)) {
#else
if (!stream->ssl->server) {
#endif
/* For client threads, ensure that the error stack is cleared */
-#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
+#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
ERR_remove_thread_state(NULL);
#else
ERR_remove_state(0);
#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L */
-#endif /* !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L */
+#endif /* !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L */
}
SSL_free(stream->ssl);
diff --git a/main/libasteriskssl.c b/main/libasteriskssl.c
index 9905b150c..0ed05e3dc 100644
--- a/main/libasteriskssl.c
+++ b/main/libasteriskssl.c
@@ -72,7 +72,7 @@ static void ssl_lock(int mode, int n, const char *file, int line)
}
}
-#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
+#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L
int SSL_library_init(void)
{
#if defined(AST_DEVMODE)
@@ -114,17 +114,20 @@ void ERR_free_strings(void)
{
/* we can't allow this to be called, ever */
}
-#endif /* !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L */
+#endif /* !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L */
#endif /* HAVE_OPENSSL */
/*!
* \internal
* \brief Common OpenSSL initialization for all of Asterisk.
+ *
+ * Not needed for OpenSSL versions >= 1.1.0
*/
int ast_ssl_init(void)
{
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && defined(OPENSSL_VERSION_NUMBER) && \
+ OPENSSL_VERSION_NUMBER < 0x10100000L
unsigned int i;
int (*real_SSL_library_init)(void);
void (*real_CRYPTO_set_id_callback)(unsigned long (*)(void));
@@ -189,7 +192,7 @@ int ast_ssl_init(void)
startup_complete = 1;
-#endif /* HAVE_OPENSSL */
+#endif /* HAVE_OPENSSL and its version < 1.1 */
return 0;
}
diff --git a/main/pbx_app.c b/main/pbx_app.c
index 0c030d12d..e0609db70 100644
--- a/main/pbx_app.c
+++ b/main/pbx_app.c
@@ -313,7 +313,6 @@ static char *handle_show_applications(struct ast_cli_entry *e, int cmd, struct a
int like = 0, describing = 0;
int total_match = 0; /* Number of matches in like clause */
int total_apps = 0; /* Number of apps registered */
- static const char * const choices[] = { "like", "describing", NULL };
switch (cmd) {
case CLI_INIT:
@@ -325,7 +324,7 @@ static char *handle_show_applications(struct ast_cli_entry *e, int cmd, struct a
" If 'describing', <text> will be a substring of the description\n";
return NULL;
case CLI_GENERATE:
- return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
+ return NULL;
}
AST_RWLIST_RDLOCK(&apps);
diff --git a/main/pbx_hangup_handler.c b/main/pbx_hangup_handler.c
index 554cb342f..84b53d0c1 100644
--- a/main/pbx_hangup_handler.c
+++ b/main/pbx_hangup_handler.c
@@ -258,7 +258,7 @@ static char *handle_show_hangup_all(struct ast_cli_entry *e, int cmd, struct ast
" Show hangup handlers for all channels.\n";
return NULL;
case CLI_GENERATE:
- return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
+ return NULL;
}
if (a->argc < 4) {
diff --git a/main/stream.c b/main/stream.c
index 0fabfc738..24844c4ab 100644
--- a/main/stream.c
+++ b/main/stream.c
@@ -239,6 +239,8 @@ int ast_stream_topology_append_stream(struct ast_stream_topology *topology, stru
return -1;
}
+ stream->position = AST_VECTOR_SIZE(&topology->streams) - 1;
+
return AST_VECTOR_SIZE(&topology->streams) - 1;
}
@@ -268,15 +270,18 @@ int ast_stream_topology_set_stream(struct ast_stream_topology *topology,
return -1;
}
- existing_stream = AST_VECTOR_GET(&topology->streams, position);
- ast_stream_destroy(existing_stream);
+ if (position < AST_VECTOR_SIZE(&topology->streams)) {
+ existing_stream = AST_VECTOR_GET(&topology->streams, position);
+ ast_stream_destroy(existing_stream);
+ }
+
+ stream->position = position;
if (position == AST_VECTOR_SIZE(&topology->streams)) {
AST_VECTOR_APPEND(&topology->streams, stream);
return 0;
}
- stream->position = position;
return AST_VECTOR_REPLACE(&topology->streams, position, stream);
}
@@ -323,7 +328,7 @@ struct ast_stream_topology *ast_stream_topology_create_from_format_cap(
/* We're transferring the initial ref so no bump needed */
stream->formats = new_cap;
stream->state = AST_STREAM_STATE_SENDRECV;
- if (!ast_stream_topology_append_stream(topology, stream)) {
+ if (ast_stream_topology_append_stream(topology, stream) == -1) {
ast_stream_destroy(stream);
ast_stream_topology_destroy(topology);
return NULL;
diff --git a/main/tcptls.c b/main/tcptls.c
index b20e04ef8..7f1421db8 100644
--- a/main/tcptls.c
+++ b/main/tcptls.c
@@ -324,12 +324,16 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client)
cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
} else
#endif
+#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+ cfg->ssl_ctx = SSL_CTX_new(TLS_client_method());
+#else
if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) {
cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
} else {
disable_ssl = 1;
cfg->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
}
+#endif
} else {
disable_ssl = 1;
cfg->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
diff --git a/res/res_sorcery_memory_cache.c b/res/res_sorcery_memory_cache.c
index 5f7ffb64e..bf2347ccd 100644
--- a/res/res_sorcery_memory_cache.c
+++ b/res/res_sorcery_memory_cache.c
@@ -1866,6 +1866,7 @@ static char *sorcery_memory_cache_expire(struct ast_cli_entry *e, int cmd, struc
static char *sorcery_memory_cache_stale(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct sorcery_memory_cache *cache;
+ int reload = 0;
switch (cmd) {
case CLI_INIT:
@@ -1881,6 +1882,9 @@ static char *sorcery_memory_cache_stale(struct ast_cli_entry *e, int cmd, struct
return sorcery_memory_cache_complete_name(a->word, a->n);
} else if (a->pos == 5) {
return sorcery_memory_cache_complete_object_name(a->argv[4], a->word, a->n);
+ } else if (a->pos == 6) {
+ static const char * const completions[] = { "reload", NULL };
+ return ast_cli_complete(a->word, completions, a->n);
} else {
return NULL;
}
@@ -1890,6 +1894,14 @@ static char *sorcery_memory_cache_stale(struct ast_cli_entry *e, int cmd, struct
return CLI_SHOWUSAGE;
}
+ if (a->argc == 7) {
+ if (!strcasecmp(a->argv[6], "reload")) {
+ reload = 1;
+ } else {
+ return CLI_SHOWUSAGE;
+ }
+ }
+
cache = ao2_find(caches, a->argv[4], OBJ_SEARCH_KEY);
if (!cache) {
ast_cli(a->fd, "Specified sorcery memory cache '%s' does not exist\n", a->argv[4]);
@@ -1910,7 +1922,7 @@ static char *sorcery_memory_cache_stale(struct ast_cli_entry *e, int cmd, struct
if (!mark_object_as_stale_in_cache(cache, a->argv[5])) {
ast_cli(a->fd, "Successfully marked object '%s' in memory cache '%s' as stale\n",
a->argv[5], a->argv[4]);
- if (a->argc == 7 && ast_true(a->argv[6])) {
+ if (reload) {
struct sorcery_memory_cached_object *cached;
cached = ao2_find(cache->objects, a->argv[5], OBJ_SEARCH_KEY | OBJ_NOLOCK);
diff --git a/tests/test_stream.c b/tests/test_stream.c
index fd78dda97..110e4e4b8 100644
--- a/tests/test_stream.c
+++ b/tests/test_stream.c
@@ -36,6 +36,7 @@
#include "asterisk/stream.h"
#include "asterisk/format.h"
#include "asterisk/format_cap.h"
+#include "asterisk/format_cache.h"
AST_TEST_DEFINE(stream_create)
{
@@ -222,6 +223,394 @@ AST_TEST_DEFINE(stream_set_state)
return AST_TEST_PASS;
}
+AST_TEST_DEFINE(stream_topology_create)
+{
+ RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_destroy);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "stream_topology_create";
+ info->category = "/main/stream/";
+ info->summary = "stream topology creation unit test";
+ info->description =
+ "Test that creating a stream topology works";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ topology = ast_stream_topology_create();
+ if (!topology) {
+ ast_test_status_update(test, "Failed to create media stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(stream_topology_clone)
+{
+ RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_destroy);
+ RAII_VAR(struct ast_stream_topology *, cloned, NULL, ast_stream_topology_destroy);
+ struct ast_stream *audio_stream, *video_stream;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "stream_topology_clone";
+ info->category = "/main/stream/";
+ info->summary = "stream topology cloning unit test";
+ info->description =
+ "Test that cloning a stream topology results in a clone with the same contents";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ topology = ast_stream_topology_create();
+ if (!topology) {
+ ast_test_status_update(test, "Failed to create media stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ audio_stream = ast_stream_create("audio", AST_MEDIA_TYPE_AUDIO);
+ if (!audio_stream) {
+ ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_append_stream(topology, audio_stream) == -1) {
+ ast_test_status_update(test, "Failed to append valid audio stream to stream topology\n");
+ ast_stream_destroy(audio_stream);
+ return AST_TEST_FAIL;
+ }
+
+ video_stream = ast_stream_create("video", AST_MEDIA_TYPE_VIDEO);
+ if (!video_stream) {
+ ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_append_stream(topology, video_stream) == -1) {
+ ast_test_status_update(test, "Failed to append valid video stream to stream topology\n");
+ ast_stream_destroy(video_stream);
+ return AST_TEST_FAIL;
+ }
+
+ cloned = ast_stream_topology_clone(topology);
+ if (!cloned) {
+ ast_test_status_update(test, "Failed to clone a perfectly good stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_count(cloned) != ast_stream_topology_get_count(topology)) {
+ ast_test_status_update(test, "Cloned stream topology does not contain same number of streams as original\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_get_type(ast_stream_topology_get_stream(cloned, 0)) != ast_stream_get_type(ast_stream_topology_get_stream(topology, 0))) {
+ ast_test_status_update(test, "Cloned audio stream does not contain same type as original\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_get_type(ast_stream_topology_get_stream(cloned, 1)) != ast_stream_get_type(ast_stream_topology_get_stream(topology, 1))) {
+ ast_test_status_update(test, "Cloned video stream does not contain same type as original\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(stream_topology_append_stream)
+{
+ RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_destroy);
+ struct ast_stream *audio_stream, *video_stream;
+ int position;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "stream_topology_append_stream";
+ info->category = "/main/stream/";
+ info->summary = "stream topology stream appending unit test";
+ info->description =
+ "Test that appending streams to a stream topology works";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ topology = ast_stream_topology_create();
+ if (!topology) {
+ ast_test_status_update(test, "Failed to create media stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ audio_stream = ast_stream_create("audio", AST_MEDIA_TYPE_AUDIO);
+ if (!audio_stream) {
+ ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ position = ast_stream_topology_append_stream(topology, audio_stream);
+ if (position == -1) {
+ ast_test_status_update(test, "Failed to append valid audio stream to stream topology\n");
+ ast_stream_destroy(audio_stream);
+ return AST_TEST_FAIL;
+ } else if (position != 0) {
+ ast_test_status_update(test, "Appended audio stream to stream topology but position is '%d' instead of 0\n",
+ position);
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_count(topology) != 1) {
+ ast_test_status_update(test, "Appended an audio stream to the stream topology but stream count is '%d' on it, not 1\n",
+ ast_stream_topology_get_count(topology));
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_stream(topology, 0) != audio_stream) {
+ ast_test_status_update(test, "Appended an audio stream to the stream topology but returned stream doesn't match\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_get_position(audio_stream) != 0) {
+ ast_test_status_update(test, "Appended audio stream says it is at position '%d' instead of 0\n",
+ ast_stream_get_position(audio_stream));
+ return AST_TEST_FAIL;
+ }
+
+ video_stream = ast_stream_create("video", AST_MEDIA_TYPE_VIDEO);
+ if (!video_stream) {
+ ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ position = ast_stream_topology_append_stream(topology, video_stream);
+ if (position == -1) {
+ ast_test_status_update(test, "Failed to append valid video stream to stream topology\n");
+ ast_stream_destroy(video_stream);
+ return AST_TEST_FAIL;
+ } else if (position != 1) {
+ ast_test_status_update(test, "Appended video stream to stream topology but position is '%d' instead of 1\n",
+ position);
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_count(topology) != 2) {
+ ast_test_status_update(test, "Appended a video stream to the stream topology but stream count is '%d' on it, not 2\n",
+ ast_stream_topology_get_count(topology));
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_stream(topology, 1) != video_stream) {
+ ast_test_status_update(test, "Appended a video stream to the stream topology but returned stream doesn't match\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_get_position(video_stream) != 1) {
+ ast_test_status_update(test, "Appended video stream says it is at position '%d' instead of 1\n",
+ ast_stream_get_position(video_stream));
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(stream_topology_set_stream)
+{
+ RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_destroy);
+ struct ast_stream *audio_stream, *video_stream;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "stream_topology_set_stream";
+ info->category = "/main/stream/";
+ info->summary = "stream topology stream setting unit test";
+ info->description =
+ "Test that setting streams at a specific position in a topology works";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ topology = ast_stream_topology_create();
+ if (!topology) {
+ ast_test_status_update(test, "Failed to create media stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ audio_stream = ast_stream_create("audio", AST_MEDIA_TYPE_AUDIO);
+ if (!audio_stream) {
+ ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_set_stream(topology, 0, audio_stream)) {
+ ast_test_status_update(test, "Failed to set an audio stream to a position where it is permitted\n");
+ ast_stream_destroy(audio_stream);
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_count(topology) != 1) {
+ ast_test_status_update(test, "Set an audio stream on the stream topology but stream count is '%d' on it, not 1\n",
+ ast_stream_topology_get_count(topology));
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_stream(topology, 0) != audio_stream) {
+ ast_test_status_update(test, "Set an audio stream on the stream topology but returned stream doesn't match\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_get_position(audio_stream) != 0) {
+ ast_test_status_update(test, "Set audio stream says it is at position '%d' instead of 0\n",
+ ast_stream_get_position(audio_stream));
+ return AST_TEST_FAIL;
+ }
+
+ video_stream = ast_stream_create("video", AST_MEDIA_TYPE_VIDEO);
+ if (!video_stream) {
+ ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_set_stream(topology, 0, video_stream)) {
+ ast_test_status_update(test, "Failed to set a video stream to a position where it is permitted\n");
+ ast_stream_destroy(video_stream);
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_count(topology) != 1) {
+ ast_test_status_update(test, "Set a video stream on the stream topology but stream count is '%d' on it, not 1\n",
+ ast_stream_topology_get_count(topology));
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_stream(topology, 0) != video_stream) {
+ ast_test_status_update(test, "Set a video stream on the stream topology but returned stream doesn't match\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_get_position(video_stream) != 0) {
+ ast_test_status_update(test, "Set video stream says it is at position '%d' instead of 0\n",
+ ast_stream_get_position(video_stream));
+ return AST_TEST_FAIL;
+ }
+
+ audio_stream = ast_stream_create("audio", AST_MEDIA_TYPE_AUDIO);
+ if (!audio_stream) {
+ ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_set_stream(topology, 1, audio_stream)) {
+ ast_test_status_update(test, "Failed to set an audio stream to a position where it is permitted\n");
+ ast_stream_destroy(audio_stream);
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_count(topology) != 2) {
+ ast_test_status_update(test, "Set an audio stream on the stream topology but stream count is '%d' on it, not 2\n",
+ ast_stream_topology_get_count(topology));
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_stream(topology, 1) != audio_stream) {
+ ast_test_status_update(test, "Set an audio stream on the stream topology but returned stream doesn't match\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_get_position(audio_stream) != 1) {
+ ast_test_status_update(test, "Set audio stream says it is at position '%d' instead of 1\n",
+ ast_stream_get_position(audio_stream));
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(stream_topology_create_from_format_cap)
+{
+ RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_destroy);
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "stream_topology_create_from_format_cap";
+ info->category = "/main/stream/";
+ info->summary = "stream topology creation from format capabilities unit test";
+ info->description =
+ "Test that creating a stream topology from format capabilities results in the expected streams";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
+ ast_test_status_update(test, "Failed to append a ulaw format to capabilities for stream topology creation\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ast_format_alaw, 0)) {
+ ast_test_status_update(test, "Failed to append an alaw format to capabilities for stream topology creation\n");
+ return AST_TEST_FAIL;
+ }
+
+ topology = ast_stream_topology_create_from_format_cap(caps);
+ if (!topology) {
+ ast_test_status_update(test, "Failed to create a stream topology using a perfectly good format capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_count(topology) != 1) {
+ ast_test_status_update(test, "Expected a stream topology with 1 stream but it has %d streams\n",
+ ast_stream_topology_get_count(topology));
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_get_type(ast_stream_topology_get_stream(topology, 0)) != AST_MEDIA_TYPE_AUDIO) {
+ ast_test_status_update(test, "Produced stream topology has a single stream of type %s instead of audio\n",
+ ast_codec_media_type2str(ast_stream_get_type(ast_stream_topology_get_stream(topology, 0))));
+ return AST_TEST_FAIL;
+ }
+
+ ast_stream_topology_destroy(topology);
+ topology = NULL;
+
+ ast_format_cap_append(caps, ast_format_h264, 0);
+
+ topology = ast_stream_topology_create_from_format_cap(caps);
+ if (!topology) {
+ ast_test_status_update(test, "Failed to create a stream topology using a perfectly good format capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_count(topology) != 2) {
+ ast_test_status_update(test, "Expected a stream topology with 2 streams but it has %d streams\n",
+ ast_stream_topology_get_count(topology));
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_get_type(ast_stream_topology_get_stream(topology, 0)) != AST_MEDIA_TYPE_AUDIO) {
+ ast_test_status_update(test, "Produced stream topology has a first stream of type %s instead of audio\n",
+ ast_codec_media_type2str(ast_stream_get_type(ast_stream_topology_get_stream(topology, 0))));
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_get_type(ast_stream_topology_get_stream(topology, 1)) != AST_MEDIA_TYPE_VIDEO) {
+ ast_test_status_update(test, "Produced stream topology has a second stream of type %s instead of video\n",
+ ast_codec_media_type2str(ast_stream_get_type(ast_stream_topology_get_stream(topology, 1))));
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
static int unload_module(void)
{
AST_TEST_UNREGISTER(stream_create);
@@ -229,6 +618,12 @@ static int unload_module(void)
AST_TEST_UNREGISTER(stream_set_type);
AST_TEST_UNREGISTER(stream_set_formats);
AST_TEST_UNREGISTER(stream_set_state);
+ AST_TEST_UNREGISTER(stream_topology_create);
+ AST_TEST_UNREGISTER(stream_topology_clone);
+ AST_TEST_UNREGISTER(stream_topology_clone);
+ AST_TEST_UNREGISTER(stream_topology_append_stream);
+ AST_TEST_UNREGISTER(stream_topology_set_stream);
+ AST_TEST_UNREGISTER(stream_topology_create_from_format_cap);
return 0;
}
@@ -239,6 +634,11 @@ static int load_module(void)
AST_TEST_REGISTER(stream_set_type);
AST_TEST_REGISTER(stream_set_formats);
AST_TEST_REGISTER(stream_set_state);
+ AST_TEST_REGISTER(stream_topology_create);
+ AST_TEST_REGISTER(stream_topology_clone);
+ AST_TEST_REGISTER(stream_topology_append_stream);
+ AST_TEST_REGISTER(stream_topology_set_stream);
+ AST_TEST_REGISTER(stream_topology_create_from_format_cap);
return AST_MODULE_LOAD_SUCCESS;
}