diff --git a/daemon/call.c b/daemon/call.c index ab5dedcc6..a2049734e 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -4590,6 +4590,198 @@ int monologue_unsubscribe(struct call_monologue *dst_ml, sdp_ng_flags *flags) { return 0; } +static bool inject_media_types_match(const struct call_media *src_media, const struct call_media *dst_media) { + if (!src_media || !dst_media) + return false; + if (src_media->type_id != MT_AUDIO || dst_media->type_id != MT_AUDIO) + return false; + return !str_cmp_str(&src_media->type, &dst_media->type); +} + +static struct call_media *inject_find_destination_media(struct call_media *src_media, + struct call_monologue *dst_ml) +{ + struct call_media *dst_media = NULL; + + if (src_media->media_id.len) { + dst_media = t_hash_table_lookup(dst_ml->media_ids, &src_media->media_id); + if (inject_media_types_match(src_media, dst_media)) + return dst_media; + } + + // best-effort match by index + if (src_media->index > 0 && src_media->index <= dst_ml->medias->len) { + dst_media = dst_ml->medias->pdata[src_media->index - 1]; + if (inject_media_types_match(src_media, dst_media)) + return dst_media; + } + + // fallback to first same media type + for (unsigned int i = 0; i < dst_ml->medias->len; i++) { + dst_media = dst_ml->medias->pdata[i]; + if (inject_media_types_match(src_media, dst_media)) + return dst_media; + } + + return NULL; +} + +static bool media_has_inject_subscriptions(const struct call_media *media) { + IQUEUE_FOREACH(&media->media_subscriptions, ms) { + if (ms->attrs.inject) + return true; + } + return false; +} + +static void inject_set_subscription_attrs(struct media_subscription *ms) { + if (!ms) + return; + ms->attrs.inject = true; + ms->attrs.offer_answer = false; + ms->attrs.egress = false; + ms->attrs.rtcp_only = false; +} + +static void inject_reconfigure_destination_media(struct call_media *dst_media, + bool force_audio_player, const sdp_ng_flags *flags) +{ + g_auto(sdp_ng_flags) local_flags; + bool reconfigured = false; + call_ng_flags_init(&local_flags, flags ? flags->opmode : OP_OTHER); + local_flags.audio_player = force_audio_player ? AP_FORCE : AP_OFF; + if (flags) + local_flags.allow_asymmetric_codecs = flags->allow_asymmetric_codecs; + + IQUEUE_FOREACH(&dst_media->media_subscriptions, ms) { + struct call_media *src_media = ms->media; + if (!inject_media_types_match(src_media, dst_media)) + continue; + + codec_handlers_update(src_media, dst_media, + .flags = &local_flags, + .allow_asymmetric = !!local_flags.allow_asymmetric_codecs, + .reset_transcoding = true); + reconfigured = true; + } + + if (force_audio_player) + audio_player_activate(dst_media); + else if (!reconfigured) { + MEDIA_CLEAR(dst_media, AUDIO_PLAYER); + audio_player_stop(dst_media); + } +} + +/* called with call->master_lock held in W */ +int monologue_inject_start(struct call_monologue *src_ml, struct call_monologue *dst_ml, sdp_ng_flags *flags) { + bool has_candidates = false; + bool linked = false; + + for (unsigned int i = 0; i < src_ml->medias->len; i++) { + struct call_media *src_media = src_ml->medias->pdata[i]; + if (!src_media || src_media->type_id != MT_AUDIO) + continue; + + struct call_media *dst_media = inject_find_destination_media(src_media, dst_ml); + if (!dst_media) + continue; + + has_candidates = true; + + struct media_subscription *existing_ms = + call_get_media_subscription(dst_media->media_subscriptions_ht, src_media); + if (existing_ms && !existing_ms->attrs.inject) { + ilog(LOG_WARN, "Inject failed for destination tag '" STR_FORMAT_M "': " + "media pair %d <- %d already has non-inject subscription", + STR_FMT_M(&dst_ml->tag), dst_media->index, src_media->index); + return -1; + } + } + + if (!has_candidates) + return -1; + + for (unsigned int i = 0; i < src_ml->medias->len; i++) { + struct call_media *src_media = src_ml->medias->pdata[i]; + if (!src_media || src_media->type_id != MT_AUDIO) + continue; + + struct call_media *dst_media = inject_find_destination_media(src_media, dst_ml); + if (!dst_media) + continue; + + struct media_subscription *dst_to_src_ms = + call_get_media_subscription(dst_media->media_subscriptions_ht, src_media); + if (!dst_to_src_ms) { + __add_media_subscription(dst_media, src_media, &(struct sink_attrs) { .inject = true }); + dst_to_src_ms = call_get_media_subscription(dst_media->media_subscriptions_ht, src_media); + } + if (!dst_to_src_ms) + continue; + + inject_set_subscription_attrs(dst_to_src_ms); + + linked = true; + } + + if (!linked) + return -1; + + for (unsigned int i = 0; i < dst_ml->medias->len; i++) { + struct call_media *dst_media = dst_ml->medias->pdata[i]; + if (!dst_media || dst_media->type_id != MT_AUDIO) + continue; + if (!media_has_inject_subscriptions(dst_media)) + continue; + inject_reconfigure_destination_media(dst_media, true, flags); + } + + update_init_monologue_subscribers(dst_ml, flags->opmode); + return 0; +} + +/* called with call->master_lock held in W */ +int monologue_inject_stop(struct call_monologue *src_ml, struct call_monologue *dst_ml, sdp_ng_flags *flags) { + bool removed_any = false; + + for (unsigned int i = 0; i < dst_ml->medias->len; i++) { + struct call_media *dst_media = dst_ml->medias->pdata[i]; + bool removed_from_media = false; + + if (!dst_media || dst_media->type_id != MT_AUDIO) + continue; + + IQUEUE_FOREACH_SAFE_DECL(&dst_media->media_subscriptions, ms); + IQUEUE_FOREACH_SAFE(&dst_media->media_subscriptions, ms) { + struct call_media *src_media = ms->media; + if (!src_media) + continue; + if (!ms->attrs.inject) + continue; + if (ms->monologue != src_ml) + continue; + + if (!__unsubscribe_media(dst_media, src_media)) + continue; + + removed_any = true; + removed_from_media = true; + } + + if (removed_from_media) { + bool still_injected = media_has_inject_subscriptions(dst_media); + inject_reconfigure_destination_media(dst_media, still_injected, flags); + } + } + + if (!removed_any) + return -1; + + update_init_monologue_subscribers(dst_ml, flags->opmode); + return 0; +} + __attribute__((nonnull(1, 2, 3))) void dialogue_connect(struct call_monologue *src_ml, struct call_monologue *dst_ml, sdp_ng_flags *flags) { diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index d45841a38..176add710 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -4358,6 +4358,77 @@ const char *call_unsubscribe_ng(ng_command_ctx_t *ctx) { return NULL; } +static const char *call_inject_ng(ng_command_ctx_t *ctx, bool start) { + g_auto(sdp_ng_flags) flags; + g_autoptr(call_t) call = NULL; + g_autoptr(call_t) call2 = NULL; + parser_arg input = ctx->req; + const ng_parser_t *parser = ctx->parser_ctx.parser; + + call_ng_process_flags(&flags, ctx); + + str source_call_id = STR_NULL; + str source_tag = STR_NULL; + + if (!flags.call_id.s) + return "No call-id in message"; + if (!flags.to_tag.s) + return "No to-tag in message"; + + parser->dict_get_str(input, "source-tag", &source_tag); + if (!source_tag.s) + return "No source-tag in message"; + + if (!parser->dict_get_str(input, "source-call-id", &source_call_id)) + source_call_id = flags.call_id; + + if (str_cmp_str(&source_call_id, &flags.call_id)) { + call_get2_ret_t ret = call_get2(&call, &call2, &flags.call_id, &source_call_id); + if (ret == CG2_NF1) + return "Unknown call-ID"; + if (ret == CG2_NF2) + return "Unknown source call-ID"; + } + else { + call = call_get(&flags.call_id); + if (!call) + return "Unknown call-ID"; + } + + struct call_monologue *dst_ml = call_get_monologue(call, &flags.to_tag); + if (!dst_ml) + return "To-tag not found"; + + struct call_monologue *src_ml = call_get_monologue(call2 ?: call, &source_tag); + if (!src_ml) + return "Source-tag not found"; + + if (src_ml == dst_ml) + return "Trying to inject to self"; + + if (call2) { + if (!call_merge(call, &call2)) + return "Failed to merge two calls into one"; + } + + int ret = start + ? monologue_inject_start(src_ml, dst_ml, &flags) + : monologue_inject_stop(src_ml, dst_ml, &flags); + if (ret) + return start ? "Failed to start inject" : "Failed to stop inject"; + + call_unlock_release_update(&call); + return NULL; +} + +const char *call_inject_start_ng(ng_command_ctx_t *ctx) { + return call_inject_ng(ctx, true); +} + +const char *call_inject_stop_ng(ng_command_ctx_t *ctx) { + return call_inject_ng(ctx, false); +} + const char *call_connect_ng(ng_command_ctx_t *ctx) { g_auto(sdp_ng_flags) flags; diff --git a/daemon/control_ng.c b/daemon/control_ng.c index a66dd0728..ba91bb86f 100644 --- a/daemon/control_ng.c +++ b/daemon/control_ng.c @@ -47,6 +47,7 @@ const char *ng_command_strings[OP_COUNT] = { "block silence media", "unblock silence media", "publish", "subscribe request", "subscribe answer", "unsubscribe", + "inject start", "inject stop", "connect", "cli", "transform" }; const char *ng_command_strings_esc[OP_COUNT] = { @@ -58,6 +59,7 @@ const char *ng_command_strings_esc[OP_COUNT] = { "block_silence_media", "unblock_silence_media", "publish", "subscribe_request", "subscribe_answer", "unsubscribe", + "inject_start", "inject_stop", "connect", "cli", "transform" }; const char *ng_command_strings_short[OP_COUNT] = { @@ -68,6 +70,7 @@ const char *ng_command_strings_short[OP_COUNT] = { "PlayDTMF", "Stats", "SlnMedia", "UnslnMedia", "BlkSlnMedia", "UnblkSlnMedia", "Pub", "SubReq", "SubAns", "Unsub", + "InjStart", "InjStop", "Conn", "CLI", "Trnsfm" }; @@ -844,6 +847,14 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons command_ctx.opmode = OP_UNSUBSCRIBE; errstr = call_unsubscribe_ng(&command_ctx); break; + case CSH_LOOKUP("inject start"): + command_ctx.opmode = OP_INJECT_START; + errstr = call_inject_start_ng(&command_ctx); + break; + case CSH_LOOKUP("inject stop"): + command_ctx.opmode = OP_INJECT_STOP; + errstr = call_inject_stop_ng(&command_ctx); + break; case CSH_LOOKUP("connect"): command_ctx.opmode = OP_CONNECT; errstr = call_connect_ng(&command_ctx); diff --git a/daemon/redis.c b/daemon/redis.c index 082b070ea..31265bc48 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -1792,7 +1792,7 @@ static int redis_link_sfds(struct redis_list *sfds, struct redis_list *streams) /** * Supports only `media-subscriptions-*` structures. * Restores media subscriptions based on: - * `unique_id`, `offer_answer`, `rtcp_only`, `egress` + * `unique_id`, `offer_answer`, `rtcp_only`, `egress`, `inject` */ static int rbl_subs_cb(str *s, callback_arg_t dummy, struct redis_list *list, void *ptr) { str token; @@ -1805,13 +1805,17 @@ static int rbl_subs_cb(str *s, callback_arg_t dummy, struct redis_list *list, vo bool offer_answer = false; bool rtcp_only = false; bool egress = false; + bool inject = false; if (str_token_sep(&token, s, '/')) { offer_answer = str_to_i(&token, 0) ? true : false; if (str_token_sep(&token, s, '/')) { rtcp_only = str_to_i(&token, 0) ? true : false; - if (str_token_sep(&token, s, '/')) + if (str_token_sep(&token, s, '/')) { egress = str_to_i(&token, 0) ? true : false; + if (str_token_sep(&token, s, '/')) + inject = str_to_i(&token, 0) ? true : false; + } } } @@ -1825,6 +1829,7 @@ static int rbl_subs_cb(str *s, callback_arg_t dummy, struct redis_list *list, vo .offer_answer = offer_answer, .rtcp_only = rtcp_only, .egress = egress, + .inject = inject, }); codec_handlers_update(other_media, media, .reset_transcoding = true); @@ -2713,11 +2718,12 @@ static str redis_encode_json(ng_parser_ctx_t *ctx, call_t *c, void **to_free) { inner = parser->dict_add_list_dup(root, tmp); IQUEUE_FOREACH(&media->media_subscriptions, ms) { - JSON_ADD_LIST_STRING("%u/%u/%u/%u", + JSON_ADD_LIST_STRING("%u/%u/%u/%u/%u", ms->media->unique_id, ms->attrs.offer_answer, ms->attrs.rtcp_only, - ms->attrs.egress); + ms->attrs.egress, + ms->attrs.inject); } snprintf(tmp, sizeof(tmp), "media-%u", media->unique_id); diff --git a/docs/ng_control_protocol.md b/docs/ng_control_protocol.md index 2792f3ea0..dce216b0b 100644 --- a/docs/ng_control_protocol.md +++ b/docs/ng_control_protocol.md @@ -63,6 +63,8 @@ Currently the following commands are defined: * subscribe request * subscribe answer * unsubscribe +* inject start +* inject stop * connect The response dictionary must contain at least one key called `result`. @@ -2603,6 +2605,58 @@ forwarding will start to the endpoint given in the answer SDP. This message is a counterpart to `subsscribe answer` to stop an established subscription. The subscription to be stopped is identified by the `to-tag`. +## `inject start` Message + +This message creates one-way media injection from a source call participant to +a destination call participant and mixes the injected audio into the destination +audio stream. + +Required keys are: + +* `call-id` and `to-tag` to identify the destination participant +* `source-tag` to identify the source participant + +An optional key `source-call-id` can be given to identify the source +participant in a different call. In this case both calls are merged internally +before creating the injection. + +The command currently applies to audio media only. + +Example: + +``` +{ + "command": "inject start", + "call-id": "main-call-id", + "to-tag": "dst-tag", + "source-call-id": "src-call-id", + "source-tag": "src-tag" +} +``` + +## `inject stop` Message + +Stops one-way media injection previously started by `inject start`. + +The same participant selection keys as for `inject start` must be provided: + +* `call-id` +* `to-tag` +* `source-tag` +* optional `source-call-id` + +Example: + +``` +{ + "command": "inject stop", + "call-id": "main-call-id", + "to-tag": "dst-tag", + "source-call-id": "src-call-id", + "source-tag": "src-tag" +} +``` + ## `connect` Message This message makes it posible to directly connect the media of two call parties diff --git a/include/call.h b/include/call.h index 46303034c..b11931de3 100644 --- a/include/call.h +++ b/include/call.h @@ -66,6 +66,7 @@ enum message_type { || (opmode == OP_START_FORWARDING || opmode == OP_STOP_FORWARDING) \ || (opmode == OP_UNSUBSCRIBE || opmode == OP_START_RECORDING) \ || (opmode == OP_STOP_RECORDING || opmode == OP_PAUSE_RECORDING) \ + || (opmode == OP_INJECT_START || opmode == OP_INJECT_STOP) \ || (opmode == OP_OTHER)) #define IS_OP_DIRECTIONAL(opmode) \ @@ -896,6 +897,10 @@ int monologue_subscribe_request(const subscription_q *srms, struct call_monologu int monologue_subscribe_answer(struct call_monologue *dst, sdp_ng_flags *flags, sdp_streams_q *streams); int monologue_unsubscribe(struct call_monologue *dst, sdp_ng_flags *); +int monologue_inject_start(struct call_monologue *src, struct call_monologue *dst, + sdp_ng_flags *flags); +int monologue_inject_stop(struct call_monologue *src, struct call_monologue *dst, + sdp_ng_flags *flags); void dialogue_connect(struct call_monologue *, struct call_monologue *, sdp_ng_flags *); bool monologue_transform(struct call_monologue *, sdp_ng_flags *, medias_q *); void monologue_destroy(struct call_monologue *ml); diff --git a/include/call_interfaces.h b/include/call_interfaces.h index 087942fae..1f3f1776b 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -352,6 +352,8 @@ const char *call_publish_ng(ng_command_ctx_t *, const char *); const char *call_subscribe_request_ng(ng_command_ctx_t *); const char *call_subscribe_answer_ng(ng_command_ctx_t *); const char *call_unsubscribe_ng(ng_command_ctx_t *); +const char *call_inject_start_ng(ng_command_ctx_t *); +const char *call_inject_stop_ng(ng_command_ctx_t *); const char *call_connect_ng(ng_command_ctx_t *); const char *call_transform_ng(ng_command_ctx_t *); diff --git a/include/control_ng.h b/include/control_ng.h index 7481b3bd1..182f9b2b8 100644 --- a/include/control_ng.h +++ b/include/control_ng.h @@ -29,6 +29,8 @@ enum ng_opmode { OP_SUBSCRIBE_REQ, OP_SUBSCRIBE_ANS, OP_UNSUBSCRIBE, + OP_INJECT_START, + OP_INJECT_STOP, OP_CONNECT, OP_CLI, OP_TRANSFORM, diff --git a/include/media_socket.h b/include/media_socket.h index 71c1cd4e5..56ad7941b 100644 --- a/include/media_socket.h +++ b/include/media_socket.h @@ -261,6 +261,7 @@ struct sink_attrs { bool rtcp_only:1; bool transcoding:1; bool egress:1; + bool inject:1; }; struct rtpext_printer { diff --git a/t/auto-daemon-tests-redis-json.pl b/t/auto-daemon-tests-redis-json.pl index 334e66e4b..eca50a367 100755 --- a/t/auto-daemon-tests-redis-json.pl +++ b/t/auto-daemon-tests-redis-json.pl @@ -297,10 +297,10 @@ $json_exp = { '3' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -550,10 +550,10 @@ $json_exp = { '3' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -812,10 +812,10 @@ $json_exp = { '3' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -1068,10 +1068,10 @@ $json_exp = { '3' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -1503,13 +1503,13 @@ $json_exp = { '7' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'media-subscriptions-2' => [ - '0/0/0/0' + '0/0/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -1948,7 +1948,7 @@ $json_exp = { ], 'media-subscriptions-0' => [], 'media-subscriptions-1' => [ - '0/0/0/0' + '0/0/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -2184,7 +2184,7 @@ $json_exp = { ], 'media-subscriptions-0' => [], 'media-subscriptions-1' => [ - '0/0/0/0' + '0/0/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -2508,10 +2508,10 @@ $json_exp = { ], 'media-subscriptions-0' => [], 'media-subscriptions-1' => [ - '0/0/0/0' + '0/0/0/0/0' ], 'media-subscriptions-2' => [ - '0/0/0/0' + '0/0/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', diff --git a/t/auto-daemon-tests-redis-subscribe.pl b/t/auto-daemon-tests-redis-subscribe.pl index ca984f753..d650cc459 100755 --- a/t/auto-daemon-tests-redis-subscribe.pl +++ b/t/auto-daemon-tests-redis-subscribe.pl @@ -391,10 +391,10 @@ $json_exp = { '3' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -532,10 +532,10 @@ my $dict = { 'type' => 'audio' }, 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'medias-0' => [ \'0' diff --git a/t/auto-daemon-tests-redis.pl b/t/auto-daemon-tests-redis.pl index 426798d9e..071947708 100755 --- a/t/auto-daemon-tests-redis.pl +++ b/t/auto-daemon-tests-redis.pl @@ -296,10 +296,10 @@ $json_exp = { '3' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -551,10 +551,10 @@ $json_exp = { '3' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -811,10 +811,10 @@ $json_exp = { '3' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -1073,10 +1073,10 @@ $json_exp = { '3' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -1329,10 +1329,10 @@ $json_exp = { '3' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -1764,13 +1764,13 @@ $json_exp = { '7' ], 'media-subscriptions-0' => [ - '1/1/0/0' + '1/1/0/0/0' ], 'media-subscriptions-1' => [ - '0/1/0/0' + '0/1/0/0/0' ], 'media-subscriptions-2' => [ - '0/0/0/0' + '0/0/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -2208,7 +2208,7 @@ $json_exp = { ], 'media-subscriptions-0' => [], 'media-subscriptions-1' => [ - '0/0/0/0' + '0/0/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -2444,7 +2444,7 @@ $json_exp = { ], 'media-subscriptions-0' => [], 'media-subscriptions-1' => [ - '0/0/0/0' + '0/0/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', @@ -2768,10 +2768,10 @@ $json_exp = { ], 'media-subscriptions-0' => [], 'media-subscriptions-1' => [ - '0/0/0/0' + '0/0/0/0/0' ], 'media-subscriptions-2' => [ - '0/0/0/0' + '0/0/0/0/0' ], 'tag-0' => { 'block_dtmf' => '0', diff --git a/t/test-stats.c b/t/test-stats.c index 6a938a43e..26fd7d8d7 100644 --- a/t/test-stats.c +++ b/t/test-stats.c @@ -280,6 +280,20 @@ int main(void) { "unsubscribes_ps_max 0 150\n" "unsubscribes_ps_avg 0 150\n" "unsubscribe_count 0 150\n" + "inject_start_time_min 0.000000 150\n" + "inject_start_time_max 0.000000 150\n" + "inject_start_time_avg 0.000000 150\n" + "inject_starts_ps_min 0 150\n" + "inject_starts_ps_max 0 150\n" + "inject_starts_ps_avg 0 150\n" + "inject_start_count 0 150\n" + "inject_stop_time_min 0.000000 150\n" + "inject_stop_time_max 0.000000 150\n" + "inject_stop_time_avg 0.000000 150\n" + "inject_stops_ps_min 0 150\n" + "inject_stops_ps_max 0 150\n" + "inject_stops_ps_avg 0 150\n" + "inject_stop_count 0 150\n" "connect_time_min 0.000000 150\n" "connect_time_max 0.000000 150\n" "connect_time_avg 0.000000 150\n" @@ -767,6 +781,22 @@ int main(void) { "0.000000\n" "avgunsubscribedelay\n" "0.000000\n" + "Min/Max/Avg inject start processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject startdelay\n" + "0.000000\n" + "maxinject startdelay\n" + "0.000000\n" + "avginject startdelay\n" + "0.000000\n" + "Min/Max/Avg inject stop processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject stopdelay\n" + "0.000000\n" + "maxinject stopdelay\n" + "0.000000\n" + "avginject stopdelay\n" + "0.000000\n" "Min/Max/Avg connect processing delay\n" "0.000000/0.000000/0.000000 sec\n" "minconnectdelay\n" @@ -1007,6 +1037,22 @@ int main(void) { "0\n" "avgunsubscriberequestrate\n" "0\n" + "Min/Max/Avg inject start requests per second\n" + "0/0/0 per sec\n" + "mininject startrequestrate\n" + "0\n" + "maxinject startrequestrate\n" + "0\n" + "avginject startrequestrate\n" + "0\n" + "Min/Max/Avg inject stop requests per second\n" + "0/0/0 per sec\n" + "mininject stoprequestrate\n" + "0\n" + "maxinject stoprequestrate\n" + "0\n" + "avginject stoprequestrate\n" + "0\n" "Min/Max/Avg connect requests per second\n" "0/0/0 per sec\n" "minconnectrequestrate\n" @@ -1194,7 +1240,7 @@ int main(void) { "{\n" "proxies\n" "[\n" - " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | Conn | CLI | Trnsfm \n" + " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | InjStart | InjStop | Conn | CLI | Trnsfm \n" "\n" "]\n" "totalpingcount\n" @@ -1251,6 +1297,10 @@ int main(void) { "0\n" "totalunsubcount\n" "0\n" + "totalinjstartcount\n" + "0\n" + "totalinjstopcount\n" + "0\n" "totalconncount\n" "0\n" "totalclicount\n" @@ -1467,6 +1517,20 @@ int main(void) { "unsubscribes_ps_max 0 150\n" "unsubscribes_ps_avg 0 150\n" "unsubscribe_count 0 150\n" + "inject_start_time_min 0.000000 150\n" + "inject_start_time_max 0.000000 150\n" + "inject_start_time_avg 0.000000 150\n" + "inject_starts_ps_min 0 150\n" + "inject_starts_ps_max 0 150\n" + "inject_starts_ps_avg 0 150\n" + "inject_start_count 0 150\n" + "inject_stop_time_min 0.000000 150\n" + "inject_stop_time_max 0.000000 150\n" + "inject_stop_time_avg 0.000000 150\n" + "inject_stops_ps_min 0 150\n" + "inject_stops_ps_max 0 150\n" + "inject_stops_ps_avg 0 150\n" + "inject_stop_count 0 150\n" "connect_time_min 0.000000 150\n" "connect_time_max 0.000000 150\n" "connect_time_avg 0.000000 150\n" @@ -1954,6 +2018,22 @@ int main(void) { "0.000000\n" "avgunsubscribedelay\n" "0.000000\n" + "Min/Max/Avg inject start processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject startdelay\n" + "0.000000\n" + "maxinject startdelay\n" + "0.000000\n" + "avginject startdelay\n" + "0.000000\n" + "Min/Max/Avg inject stop processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject stopdelay\n" + "0.000000\n" + "maxinject stopdelay\n" + "0.000000\n" + "avginject stopdelay\n" + "0.000000\n" "Min/Max/Avg connect processing delay\n" "0.000000/0.000000/0.000000 sec\n" "minconnectdelay\n" @@ -2194,6 +2274,22 @@ int main(void) { "0\n" "avgunsubscriberequestrate\n" "0\n" + "Min/Max/Avg inject start requests per second\n" + "0/0/0 per sec\n" + "mininject startrequestrate\n" + "0\n" + "maxinject startrequestrate\n" + "0\n" + "avginject startrequestrate\n" + "0\n" + "Min/Max/Avg inject stop requests per second\n" + "0/0/0 per sec\n" + "mininject stoprequestrate\n" + "0\n" + "maxinject stoprequestrate\n" + "0\n" + "avginject stoprequestrate\n" + "0\n" "Min/Max/Avg connect requests per second\n" "0/0/0 per sec\n" "minconnectrequestrate\n" @@ -2381,7 +2477,7 @@ int main(void) { "{\n" "proxies\n" "[\n" - " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | Conn | CLI | Trnsfm \n" + " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | InjStart | InjStop | Conn | CLI | Trnsfm \n" "\n" "]\n" "totalpingcount\n" @@ -2438,6 +2534,10 @@ int main(void) { "0\n" "totalunsubcount\n" "0\n" + "totalinjstartcount\n" + "0\n" + "totalinjstopcount\n" + "0\n" "totalconncount\n" "0\n" "totalclicount\n" @@ -2651,6 +2751,20 @@ int main(void) { "unsubscribes_ps_max 0 150\n" "unsubscribes_ps_avg 0 150\n" "unsubscribe_count 0 150\n" + "inject_start_time_min 0.000000 150\n" + "inject_start_time_max 0.000000 150\n" + "inject_start_time_avg 0.000000 150\n" + "inject_starts_ps_min 0 150\n" + "inject_starts_ps_max 0 150\n" + "inject_starts_ps_avg 0 150\n" + "inject_start_count 0 150\n" + "inject_stop_time_min 0.000000 150\n" + "inject_stop_time_max 0.000000 150\n" + "inject_stop_time_avg 0.000000 150\n" + "inject_stops_ps_min 0 150\n" + "inject_stops_ps_max 0 150\n" + "inject_stops_ps_avg 0 150\n" + "inject_stop_count 0 150\n" "connect_time_min 0.000000 150\n" "connect_time_max 0.000000 150\n" "connect_time_avg 0.000000 150\n" @@ -3138,6 +3252,22 @@ int main(void) { "0.000000\n" "avgunsubscribedelay\n" "0.000000\n" + "Min/Max/Avg inject start processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject startdelay\n" + "0.000000\n" + "maxinject startdelay\n" + "0.000000\n" + "avginject startdelay\n" + "0.000000\n" + "Min/Max/Avg inject stop processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject stopdelay\n" + "0.000000\n" + "maxinject stopdelay\n" + "0.000000\n" + "avginject stopdelay\n" + "0.000000\n" "Min/Max/Avg connect processing delay\n" "0.000000/0.000000/0.000000 sec\n" "minconnectdelay\n" @@ -3378,6 +3508,22 @@ int main(void) { "0\n" "avgunsubscriberequestrate\n" "0\n" + "Min/Max/Avg inject start requests per second\n" + "0/0/0 per sec\n" + "mininject startrequestrate\n" + "0\n" + "maxinject startrequestrate\n" + "0\n" + "avginject startrequestrate\n" + "0\n" + "Min/Max/Avg inject stop requests per second\n" + "0/0/0 per sec\n" + "mininject stoprequestrate\n" + "0\n" + "maxinject stoprequestrate\n" + "0\n" + "avginject stoprequestrate\n" + "0\n" "Min/Max/Avg connect requests per second\n" "0/0/0 per sec\n" "minconnectrequestrate\n" @@ -3565,7 +3711,7 @@ int main(void) { "{\n" "proxies\n" "[\n" - " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | Conn | CLI | Trnsfm \n" + " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | InjStart | InjStop | Conn | CLI | Trnsfm \n" "\n" "]\n" "totalpingcount\n" @@ -3622,6 +3768,10 @@ int main(void) { "0\n" "totalunsubcount\n" "0\n" + "totalinjstartcount\n" + "0\n" + "totalinjstopcount\n" + "0\n" "totalconncount\n" "0\n" "totalclicount\n" @@ -3854,6 +4004,20 @@ int main(void) { "unsubscribes_ps_max 0 157\n" "unsubscribes_ps_avg 0 157\n" "unsubscribe_count 0 157\n" + "inject_start_time_min 0.000000 157\n" + "inject_start_time_max 0.000000 157\n" + "inject_start_time_avg 0.000000 157\n" + "inject_starts_ps_min 0 157\n" + "inject_starts_ps_max 0 157\n" + "inject_starts_ps_avg 0 157\n" + "inject_start_count 0 157\n" + "inject_stop_time_min 0.000000 157\n" + "inject_stop_time_max 0.000000 157\n" + "inject_stop_time_avg 0.000000 157\n" + "inject_stops_ps_min 0 157\n" + "inject_stops_ps_max 0 157\n" + "inject_stops_ps_avg 0 157\n" + "inject_stop_count 0 157\n" "connect_time_min 0.000000 157\n" "connect_time_max 0.000000 157\n" "connect_time_avg 0.000000 157\n" @@ -4341,6 +4505,22 @@ int main(void) { "0.000000\n" "avgunsubscribedelay\n" "0.000000\n" + "Min/Max/Avg inject start processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject startdelay\n" + "0.000000\n" + "maxinject startdelay\n" + "0.000000\n" + "avginject startdelay\n" + "0.000000\n" + "Min/Max/Avg inject stop processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject stopdelay\n" + "0.000000\n" + "maxinject stopdelay\n" + "0.000000\n" + "avginject stopdelay\n" + "0.000000\n" "Min/Max/Avg connect processing delay\n" "0.000000/0.000000/0.000000 sec\n" "minconnectdelay\n" @@ -4581,6 +4761,22 @@ int main(void) { "0\n" "avgunsubscriberequestrate\n" "0\n" + "Min/Max/Avg inject start requests per second\n" + "0/0/0 per sec\n" + "mininject startrequestrate\n" + "0\n" + "maxinject startrequestrate\n" + "0\n" + "avginject startrequestrate\n" + "0\n" + "Min/Max/Avg inject stop requests per second\n" + "0/0/0 per sec\n" + "mininject stoprequestrate\n" + "0\n" + "maxinject stoprequestrate\n" + "0\n" + "avginject stoprequestrate\n" + "0\n" "Min/Max/Avg connect requests per second\n" "0/0/0 per sec\n" "minconnectrequestrate\n" @@ -4768,7 +4964,7 @@ int main(void) { "{\n" "proxies\n" "[\n" - " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | Conn | CLI | Trnsfm \n" + " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | InjStart | InjStop | Conn | CLI | Trnsfm \n" "\n" "]\n" "totalpingcount\n" @@ -4825,6 +5021,10 @@ int main(void) { "0\n" "totalunsubcount\n" "0\n" + "totalinjstartcount\n" + "0\n" + "totalinjstopcount\n" + "0\n" "totalconncount\n" "0\n" "totalclicount\n" @@ -5046,6 +5246,20 @@ int main(void) { "unsubscribes_ps_max 0 157\n" "unsubscribes_ps_avg 0 157\n" "unsubscribe_count 0 157\n" + "inject_start_time_min 0.000000 157\n" + "inject_start_time_max 0.000000 157\n" + "inject_start_time_avg 0.000000 157\n" + "inject_starts_ps_min 0 157\n" + "inject_starts_ps_max 0 157\n" + "inject_starts_ps_avg 0 157\n" + "inject_start_count 0 157\n" + "inject_stop_time_min 0.000000 157\n" + "inject_stop_time_max 0.000000 157\n" + "inject_stop_time_avg 0.000000 157\n" + "inject_stops_ps_min 0 157\n" + "inject_stops_ps_max 0 157\n" + "inject_stops_ps_avg 0 157\n" + "inject_stop_count 0 157\n" "connect_time_min 0.000000 157\n" "connect_time_max 0.000000 157\n" "connect_time_avg 0.000000 157\n" @@ -5533,6 +5747,22 @@ int main(void) { "0.000000\n" "avgunsubscribedelay\n" "0.000000\n" + "Min/Max/Avg inject start processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject startdelay\n" + "0.000000\n" + "maxinject startdelay\n" + "0.000000\n" + "avginject startdelay\n" + "0.000000\n" + "Min/Max/Avg inject stop processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject stopdelay\n" + "0.000000\n" + "maxinject stopdelay\n" + "0.000000\n" + "avginject stopdelay\n" + "0.000000\n" "Min/Max/Avg connect processing delay\n" "0.000000/0.000000/0.000000 sec\n" "minconnectdelay\n" @@ -5773,6 +6003,22 @@ int main(void) { "0\n" "avgunsubscriberequestrate\n" "0\n" + "Min/Max/Avg inject start requests per second\n" + "0/0/0 per sec\n" + "mininject startrequestrate\n" + "0\n" + "maxinject startrequestrate\n" + "0\n" + "avginject startrequestrate\n" + "0\n" + "Min/Max/Avg inject stop requests per second\n" + "0/0/0 per sec\n" + "mininject stoprequestrate\n" + "0\n" + "maxinject stoprequestrate\n" + "0\n" + "avginject stoprequestrate\n" + "0\n" "Min/Max/Avg connect requests per second\n" "0/0/0 per sec\n" "minconnectrequestrate\n" @@ -5960,7 +6206,7 @@ int main(void) { "{\n" "proxies\n" "[\n" - " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | Conn | CLI | Trnsfm \n" + " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | InjStart | InjStop | Conn | CLI | Trnsfm \n" "\n" "]\n" "totalpingcount\n" @@ -6017,6 +6263,10 @@ int main(void) { "0\n" "totalunsubcount\n" "0\n" + "totalinjstartcount\n" + "0\n" + "totalinjstopcount\n" + "0\n" "totalconncount\n" "0\n" "totalclicount\n" @@ -6232,6 +6482,20 @@ int main(void) { "unsubscribes_ps_max 0 200\n" "unsubscribes_ps_avg 0 200\n" "unsubscribe_count 0 200\n" + "inject_start_time_min 0.000000 200\n" + "inject_start_time_max 0.000000 200\n" + "inject_start_time_avg 0.000000 200\n" + "inject_starts_ps_min 0 200\n" + "inject_starts_ps_max 0 200\n" + "inject_starts_ps_avg 0 200\n" + "inject_start_count 0 200\n" + "inject_stop_time_min 0.000000 200\n" + "inject_stop_time_max 0.000000 200\n" + "inject_stop_time_avg 0.000000 200\n" + "inject_stops_ps_min 0 200\n" + "inject_stops_ps_max 0 200\n" + "inject_stops_ps_avg 0 200\n" + "inject_stop_count 0 200\n" "connect_time_min 0.000000 200\n" "connect_time_max 0.000000 200\n" "connect_time_avg 0.000000 200\n" @@ -6719,6 +6983,22 @@ int main(void) { "0.000000\n" "avgunsubscribedelay\n" "0.000000\n" + "Min/Max/Avg inject start processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject startdelay\n" + "0.000000\n" + "maxinject startdelay\n" + "0.000000\n" + "avginject startdelay\n" + "0.000000\n" + "Min/Max/Avg inject stop processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject stopdelay\n" + "0.000000\n" + "maxinject stopdelay\n" + "0.000000\n" + "avginject stopdelay\n" + "0.000000\n" "Min/Max/Avg connect processing delay\n" "0.000000/0.000000/0.000000 sec\n" "minconnectdelay\n" @@ -6959,6 +7239,22 @@ int main(void) { "0\n" "avgunsubscriberequestrate\n" "0\n" + "Min/Max/Avg inject start requests per second\n" + "0/0/0 per sec\n" + "mininject startrequestrate\n" + "0\n" + "maxinject startrequestrate\n" + "0\n" + "avginject startrequestrate\n" + "0\n" + "Min/Max/Avg inject stop requests per second\n" + "0/0/0 per sec\n" + "mininject stoprequestrate\n" + "0\n" + "maxinject stoprequestrate\n" + "0\n" + "avginject stoprequestrate\n" + "0\n" "Min/Max/Avg connect requests per second\n" "0/0/0 per sec\n" "minconnectrequestrate\n" @@ -7146,7 +7442,7 @@ int main(void) { "{\n" "proxies\n" "[\n" - " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | Conn | CLI | Trnsfm \n" + " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | InjStart | InjStop | Conn | CLI | Trnsfm \n" "\n" "]\n" "totalpingcount\n" @@ -7203,6 +7499,10 @@ int main(void) { "0\n" "totalunsubcount\n" "0\n" + "totalinjstartcount\n" + "0\n" + "totalinjstopcount\n" + "0\n" "totalconncount\n" "0\n" "totalclicount\n" @@ -7421,6 +7721,20 @@ int main(void) { "unsubscribes_ps_max 0 200\n" "unsubscribes_ps_avg 0 200\n" "unsubscribe_count 0 200\n" + "inject_start_time_min 0.000000 200\n" + "inject_start_time_max 0.000000 200\n" + "inject_start_time_avg 0.000000 200\n" + "inject_starts_ps_min 0 200\n" + "inject_starts_ps_max 0 200\n" + "inject_starts_ps_avg 0 200\n" + "inject_start_count 0 200\n" + "inject_stop_time_min 0.000000 200\n" + "inject_stop_time_max 0.000000 200\n" + "inject_stop_time_avg 0.000000 200\n" + "inject_stops_ps_min 0 200\n" + "inject_stops_ps_max 0 200\n" + "inject_stops_ps_avg 0 200\n" + "inject_stop_count 0 200\n" "connect_time_min 0.000000 200\n" "connect_time_max 0.000000 200\n" "connect_time_avg 0.000000 200\n" @@ -7908,6 +8222,22 @@ int main(void) { "0.000000\n" "avgunsubscribedelay\n" "0.000000\n" + "Min/Max/Avg inject start processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject startdelay\n" + "0.000000\n" + "maxinject startdelay\n" + "0.000000\n" + "avginject startdelay\n" + "0.000000\n" + "Min/Max/Avg inject stop processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "mininject stopdelay\n" + "0.000000\n" + "maxinject stopdelay\n" + "0.000000\n" + "avginject stopdelay\n" + "0.000000\n" "Min/Max/Avg connect processing delay\n" "0.000000/0.000000/0.000000 sec\n" "minconnectdelay\n" @@ -8148,6 +8478,22 @@ int main(void) { "0\n" "avgunsubscriberequestrate\n" "0\n" + "Min/Max/Avg inject start requests per second\n" + "0/0/0 per sec\n" + "mininject startrequestrate\n" + "0\n" + "maxinject startrequestrate\n" + "0\n" + "avginject startrequestrate\n" + "0\n" + "Min/Max/Avg inject stop requests per second\n" + "0/0/0 per sec\n" + "mininject stoprequestrate\n" + "0\n" + "maxinject stoprequestrate\n" + "0\n" + "avginject stoprequestrate\n" + "0\n" "Min/Max/Avg connect requests per second\n" "0/0/0 per sec\n" "minconnectrequestrate\n" @@ -8335,7 +8681,7 @@ int main(void) { "{\n" "proxies\n" "[\n" - " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | Conn | CLI | Trnsfm \n" + " Proxy | Ping | Offer | Answer | Delete | Query | List | StartRec | StopRec | PauseRec | StartFwd | StopFwd | BlkDTMF | UnblkDTMF | BlkMedia | UnblkMedia | PlayMedia | StopMedia | PlayDTMF | Stats | SlnMedia | UnslnMedia | BlkSlnMedia | UnblkSlnMedia | Pub | SubReq | SubAns | Unsub | InjStart | InjStop | Conn | CLI | Trnsfm \n" "\n" "]\n" "totalpingcount\n" @@ -8392,6 +8738,10 @@ int main(void) { "0\n" "totalunsubcount\n" "0\n" + "totalinjstartcount\n" + "0\n" + "totalinjstopcount\n" + "0\n" "totalconncount\n" "0\n" "totalclicount\n"