diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/app.c | 13 | ||||
-rw-r--r-- | main/bridge_channel.c | 30 | ||||
-rw-r--r-- | main/channel.c | 5 | ||||
-rw-r--r-- | main/config.c | 49 | ||||
-rw-r--r-- | main/config_options.c | 36 | ||||
-rw-r--r-- | main/core_unreal.c | 13 | ||||
-rw-r--r-- | main/rtp_engine.c | 68 |
7 files changed, 187 insertions, 27 deletions
diff --git a/main/app.c b/main/app.c index 1eb0741ee..69c96c06c 100644 --- a/main/app.c +++ b/main/app.c @@ -3060,19 +3060,32 @@ int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen uni case 'h': case 'H': unit = TIMELEN_HOURS; + if (u[1] != '\0') { + return -1; + } break; case 's': case 'S': unit = TIMELEN_SECONDS; + if (u[1] != '\0') { + return -1; + } break; case 'm': case 'M': if (toupper(u[1]) == 'S') { unit = TIMELEN_MILLISECONDS; + if (u[2] != '\0') { + return -1; + } } else if (u[1] == '\0') { unit = TIMELEN_MINUTES; + } else { + return -1; } break; + default: + return -1; } } diff --git a/main/bridge_channel.c b/main/bridge_channel.c index e8ab8a898..2e943000c 100644 --- a/main/bridge_channel.c +++ b/main/bridge_channel.c @@ -998,21 +998,6 @@ int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, st return 0; } - if (ast_channel_is_multistream(bridge_channel->chan) && - (fr->frametype == AST_FRAME_IMAGE || fr->frametype == AST_FRAME_TEXT || - fr->frametype == AST_FRAME_VIDEO || fr->frametype == AST_FRAME_VOICE)) { - /* Media frames need to be mapped to an appropriate write stream */ - dup->stream_num = AST_VECTOR_GET( - &bridge_channel->stream_map.to_bridge, fr->stream_num); - if (dup->stream_num == -1) { - ast_bridge_channel_unlock(bridge_channel); - bridge_frame_free(dup); - return 0; - } - } else { - dup->stream_num = -1; - } - AST_LIST_INSERT_TAIL(&bridge_channel->wr_queue, dup, frame_list); if (ast_alertpipe_write(bridge_channel->alert_pipe)) { ast_log(LOG_ERROR, "We couldn't write alert pipe for %p(%s)... something is VERY wrong\n", @@ -2455,15 +2440,26 @@ static void bridge_handle_trip(struct ast_bridge_channel *bridge_channel) } if (bridge_channel->features->mute) { - frame = ast_read_noaudio(bridge_channel->chan); + frame = ast_read_stream_noaudio(bridge_channel->chan); } else { - frame = ast_read(bridge_channel->chan); + frame = ast_read_stream(bridge_channel->chan); } if (!frame) { ast_bridge_channel_kick(bridge_channel, 0); return; } + + if (ast_channel_is_multistream(bridge_channel->chan) && + (frame->frametype == AST_FRAME_IMAGE || frame->frametype == AST_FRAME_TEXT || + frame->frametype == AST_FRAME_VIDEO || frame->frametype == AST_FRAME_VOICE)) { + /* Media frames need to be mapped to an appropriate write stream */ + frame->stream_num = AST_VECTOR_GET( + &bridge_channel->stream_map.to_bridge, frame->stream_num); + } else { + frame->stream_num = -1; + } + switch (frame->frametype) { case AST_FRAME_CONTROL: switch (frame->subclass.integer) { diff --git a/main/channel.c b/main/channel.c index 27efb2ee3..66825559c 100644 --- a/main/channel.c +++ b/main/channel.c @@ -4183,6 +4183,11 @@ struct ast_frame *ast_read_noaudio(struct ast_channel *chan) return __ast_read(chan, 1, 1); } +struct ast_frame *ast_read_stream_noaudio(struct ast_channel *chan) +{ + return __ast_read(chan, 1, 0); +} + int ast_indicate(struct ast_channel *chan, int condition) { return ast_indicate_data(chan, condition, NULL, 0); diff --git a/main/config.c b/main/config.c index a3e09f67e..3d8dcfb3d 100644 --- a/main/config.c +++ b/main/config.c @@ -3741,6 +3741,55 @@ uint32_done: break; } + case PARSE_TIMELEN: + { + int x = 0; + int *result = p_result; + int def = result ? *result : 0; + int high = INT_MAX; + int low = INT_MIN; + enum ast_timelen defunit; + + defunit = va_arg(ap, enum ast_timelen); + /* optional arguments: default value and/or (low, high) */ + if (flags & PARSE_DEFAULT) { + def = va_arg(ap, int); + } + if (flags & (PARSE_IN_RANGE | PARSE_OUT_RANGE)) { + low = va_arg(ap, int); + high = va_arg(ap, int); + } + if (ast_strlen_zero(arg)) { + error = 1; + goto timelen_done; + } + error = ast_app_parse_timelen(arg, &x, defunit); + if (error || x < INT_MIN || x > INT_MAX) { + /* Parse error, or type out of int bounds */ + error = 1; + goto timelen_done; + } + error = (x < low) || (x > high); + if (flags & PARSE_RANGE_DEFAULTS) { + if (x < low) { + def = low; + } else if (x > high) { + def = high; + } + } + if (flags & PARSE_OUT_RANGE) { + error = !error; + } +timelen_done: + if (result) { + *result = error ? def : x; + } + + ast_debug(3, "extract timelen from [%s] in [%d, %d] gives [%d](%d)\n", + arg, low, high, result ? *result : x, error); + break; + } + case PARSE_DOUBLE: { double *result = p_result; diff --git a/main/config_options.c b/main/config_options.c index c80777906..8eacbda35 100644 --- a/main/config_options.c +++ b/main/config_options.c @@ -34,6 +34,7 @@ #include "asterisk/config_options.h" #include "asterisk/stringfields.h" #include "asterisk/acl.h" +#include "asterisk/app.h" #include "asterisk/frame.h" #include "asterisk/xmldoc.h" #include "asterisk/cli.h" @@ -118,6 +119,7 @@ static void config_option_destroy(void *obj) static int int_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); static int uint_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); +static int timelen_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); static int double_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); static int sockaddr_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); static int stringfield_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); @@ -151,6 +153,7 @@ static aco_option_handler ast_config_option_default_handler(enum aco_option_type case OPT_SOCKADDR_T: return sockaddr_handler_fn; case OPT_STRINGFIELD_T: return stringfield_handler_fn; case OPT_UINT_T: return uint_handler_fn; + case OPT_TIMELEN_T: return timelen_handler_fn; case OPT_CUSTOM_T: return NULL; } @@ -1378,6 +1381,39 @@ static int uint_handler_fn(const struct aco_option *opt, struct ast_variable *va return res; } +/*! \brief Default option handler for timelen signed integers + * \note For a description of the opt->flags and opt->args values, see the documentation for + * enum aco_option_type in config_options.h + */ +static int timelen_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) +{ + int *field = (int *)(obj + opt->args[0]); + unsigned int flags = PARSE_TIMELEN | opt->flags; + int res = 0; + if (opt->flags & PARSE_IN_RANGE) { + if (opt->flags & PARSE_DEFAULT) { + res = ast_parse_arg(var->value, flags, field, (enum ast_timelen) opt->args[1], (int) opt->args[2], (int) opt->args[3], opt->args[4]); + } else { + res = ast_parse_arg(var->value, flags, field, (enum ast_timelen) opt->args[1], (int) opt->args[2], (int) opt->args[3]); + } + if (res) { + if (opt->flags & PARSE_RANGE_DEFAULTS) { + ast_log(LOG_WARNING, "Failed to set %s=%s. Set to %d instead due to range limit (%d, %d)\n", var->name, var->value, *field, (int) opt->args[2], (int) opt->args[3]); + res = 0; + } else if (opt->flags & PARSE_DEFAULT) { + ast_log(LOG_WARNING, "Failed to set %s=%s, Set to default value %d instead.\n", var->name, var->value, *field); + res = 0; + } + } + } else if ((opt->flags & PARSE_DEFAULT) && ast_parse_arg(var->value, flags, field, (enum ast_timelen) opt->args[1], (int) opt->args[2])) { + ast_log(LOG_WARNING, "Attempted to set %s=%s, but set it to %d instead due to default)\n", var->name, var->value, *field); + } else { + res = ast_parse_arg(var->value, flags, field, (enum ast_timelen) opt->args[1]); + } + + return res; +} + /*! \brief Default option handler for doubles * \note For a description of the opt->flags and opt->args values, see the documentation for * enum aco_option_type in config_options.h diff --git a/main/core_unreal.c b/main/core_unreal.c index 5da740877..3db6a4dbd 100644 --- a/main/core_unreal.c +++ b/main/core_unreal.c @@ -323,6 +323,19 @@ int ast_unreal_write(struct ast_channel *ast, struct ast_frame *f) return -1; } + /* If we are told to write a frame with a type that has no corresponding + * stream on the channel then drop it. + */ + if (f->frametype == AST_FRAME_VOICE) { + if (!ast_channel_get_default_stream(ast, AST_MEDIA_TYPE_AUDIO)) { + return 0; + } + } else if (f->frametype == AST_FRAME_VIDEO) { + if (!ast_channel_get_default_stream(ast, AST_MEDIA_TYPE_VIDEO)) { + return 0; + } + } + /* Just queue for delivery to the other side */ ao2_ref(p, 1); ao2_lock(p); diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 9cfae09f4..abd4b1fcf 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -1495,21 +1495,24 @@ static int rtp_codecs_find_non_primary_dynamic_rx(struct ast_rtp_codecs *codecs) * \param asterisk_format Non-zero if the given Asterisk format is present * \param format Asterisk format to look for * \param code The format to look for + * \param explicit Require the provided code to be explicitly used * * \note It is assumed that static_RTP_PT_lock is at least read locked before calling. * * \retval Numerical payload type * \retval -1 if could not assign. */ -static int rtp_codecs_assign_payload_code_rx(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code) +static int rtp_codecs_assign_payload_code_rx(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code, int explicit) { - int payload; + int payload = code; struct ast_rtp_payload_type *new_type; - payload = find_static_payload_type(asterisk_format, format, code); + if (!explicit) { + payload = find_static_payload_type(asterisk_format, format, code); - if (payload < 0 && (!asterisk_format || ast_option_rtpusedynamic)) { - return payload; + if (payload < 0 && (!asterisk_format || ast_option_rtpusedynamic)) { + return payload; + } } new_type = rtp_payload_type_alloc(format, payload, code, 1); @@ -1525,9 +1528,9 @@ static int rtp_codecs_assign_payload_code_rx(struct ast_rtp_codecs *codecs, int * The payload type is a static assignment * or our default dynamic position is available. */ - rtp_codecs_payload_replace_rx(codecs, payload, new_type); - } else if (-1 < (payload = find_unused_payload(codecs)) - || -1 < (payload = rtp_codecs_find_non_primary_dynamic_rx(codecs))) { + rtp_codecs_payload_replace_rx(codecs, payload, new_type); + } else if (!explicit && (-1 < (payload = find_unused_payload(codecs)) + || -1 < (payload = rtp_codecs_find_non_primary_dynamic_rx(codecs)))) { /* * We found the first available empty dynamic position * or we found a mapping that should no longer be @@ -1535,6 +1538,11 @@ static int rtp_codecs_assign_payload_code_rx(struct ast_rtp_codecs *codecs, int */ new_type->payload = payload; rtp_codecs_payload_replace_rx(codecs, payload, new_type); + } else if (explicit) { + /* + * They explicitly requested this payload number be used but it couldn't be + */ + payload = -1; } else { /* * There are no empty or non-primary dynamic positions @@ -1595,13 +1603,18 @@ int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_form if (payload < 0) { payload = rtp_codecs_assign_payload_code_rx(codecs, asterisk_format, format, - code); + code, 0); } ast_rwlock_unlock(&static_RTP_PT_lock); return payload; } +int ast_rtp_codecs_payload_set_rx(struct ast_rtp_codecs *codecs, int code, struct ast_format *format) +{ + return rtp_codecs_assign_payload_code_rx(codecs, 1, format, code, 1); +} + int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code) { struct ast_rtp_payload_type *type; @@ -2424,7 +2437,7 @@ int ast_rtp_instance_add_srtp_policy(struct ast_rtp_instance *instance, struct a if (!*srtp) { res = res_srtp->create(srtp, instance, remote_policy); - } else { + } else if (remote_policy) { res = res_srtp->replace(srtp, instance, remote_policy); } if (!res) { @@ -3366,3 +3379,38 @@ const char *ast_rtp_instance_get_cname(struct ast_rtp_instance *rtp) return cname; } + +int ast_rtp_instance_bundle(struct ast_rtp_instance *child, struct ast_rtp_instance *parent) +{ + int res = -1; + + if (child->engine != parent->engine) { + return -1; + } + + ao2_lock(child); + if (child->engine->bundle) { + res = child->engine->bundle(child, parent); + } + ao2_unlock(child); + + return res; +} + +void ast_rtp_instance_set_remote_ssrc(struct ast_rtp_instance *rtp, unsigned int ssrc) +{ + ao2_lock(rtp); + if (rtp->engine->set_remote_ssrc) { + rtp->engine->set_remote_ssrc(rtp, ssrc); + } + ao2_unlock(rtp); +} + +void ast_rtp_instance_set_stream_num(struct ast_rtp_instance *rtp, int stream_num) +{ + ao2_lock(rtp); + if (rtp->engine->set_stream_num) { + rtp->engine->set_stream_num(rtp, stream_num); + } + ao2_unlock(rtp); +}
\ No newline at end of file |