MT#55283 add inject start/stop commands for one-way audio injection

New NG protocol commands that mix audio from a source participant
into a destination participant's stream without a full offer/answer
exchange.

- inject start: creates one-way subscription with audio_player mixing
- inject stop: removes injection and restores original codec routing
- Supports cross-call injection via source-call-id (merges calls internally)
- inject attribute persisted through Redis for HA failover
- Audio-only; matches media by media-id, index, then type fallback

Closes #2082

Change-Id: Ib88113b021a4b76bf98892eb1af60c0b36c0d6d3
pull/2056/head
Nikolay Feshenko 2 months ago committed by Richard Fuchs
parent 14919df584
commit 352bda7035

@ -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) {

@ -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;

@ -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);

@ -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);

@ -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

@ -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);

@ -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 *);

@ -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,

@ -261,6 +261,7 @@ struct sink_attrs {
bool rtcp_only:1;
bool transcoding:1;
bool egress:1;
bool inject:1;
};
struct rtpext_printer {

@ -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',

@ -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'

@ -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',

@ -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"

Loading…
Cancel
Save