From 4bf3644e1dda3d153147138eb661c789f63b6b45 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 14 Apr 2026 08:32:18 -0400 Subject: [PATCH] MT#55283 add mesh method Change-Id: I66aa4cd2e519f707b76b4b1c2004a45c748c5c16 --- daemon/call_flags.c | 40 ++ daemon/call_interfaces.c | 68 +- daemon/control_ng.c | 10 +- docs/ng_control_protocol.md | 24 + include/call_flags.h | 12 + include/call_interfaces.h | 1 + include/control_ng.h | 3 + t/auto-daemon-tests-create.pl | 1251 +++++++++++++++++++++++++++++++++ t/test-stats.c | 189 ++++- utils/rtpengine-ng-client | 1 + 10 files changed, 1588 insertions(+), 11 deletions(-) diff --git a/daemon/call_flags.c b/daemon/call_flags.c index 41e971f3e..903fab561 100644 --- a/daemon/call_flags.c +++ b/daemon/call_flags.c @@ -962,6 +962,9 @@ const char *call_ng_flags_flags(str *s, unsigned int idx, helper_arg arg) { case CSH_LOOKUP("unidirectional"): out->unidirectional = true; break; + case CSH_LOOKUP("unsubscribe"): + out->unsubscribe = true; + break; case CSH_LOOKUP("webrtc"): case CSH_LOOKUP("webRTC"): case CSH_LOOKUP("WebRTC"): @@ -1368,6 +1371,31 @@ static const char *call_ng_media_iter(const ng_parser_t *parser, parser_arg item return parser->dict_iter(parser, item, call_ng_media, media); } +static const char *call_ng_tag(const ng_parser_t *parser, str *key, parser_arg value, struct ng_tag *tag) { + str s = STR_NULL; + parser->get_str(value, &s); + switch (__csh_lookup(key)) { + case CSH_LOOKUP("from"): + tag->from = s; + break; + case CSH_LOOKUP("to"): + return call_ng_flags_str_list(parser, value, call_ng_flags_esc_str_list, &tag->to); + } + + return NULL; +} + +static const char *call_ng_tags_iter(const ng_parser_t *parser, parser_arg item, sdp_ng_flags *out) { + __auto_type tag = g_new0(struct ng_tag, 1); + t_queue_push_tail(&out->tags, tag); + const char *err = parser->dict_iter(parser, item, call_ng_tag, tag); + if (err) + return err; + if (!tag->from.len) + return "Empty/missing from-tag"; + return NULL; +} + const char *call_ng_main_flags(const ng_parser_t *parser, str *key, parser_arg value, helper_arg arg) { str s = STR_NULL; sdp_ng_flags *out = arg.flags; @@ -1473,6 +1501,9 @@ const char *call_ng_main_flags(const ng_parser_t *parser, str *key, parser_arg v case CSH_LOOKUP("call ID"): out->call_id = s; break; + case CSH_LOOKUP("calls"): + call_ng_flags_str_list(parser, value, call_ng_flags_esc_str_list, &out->calls); + break; case CSH_LOOKUP("code"): case CSH_LOOKUP("digit"): out->digit = parser->get_int_str(value, out->digit); @@ -1980,6 +2011,8 @@ const char *call_ng_main_flags(const ng_parser_t *parser, str *key, parser_arg v out->t38_version = parser->get_int_str(value, out->t38_version); break; #endif + case CSH_LOOKUP("tags"): + return parser->list_iter(parser, value, NULL, call_ng_tags_iter, out); case CSH_LOOKUP("template"):; str *tplate = t_hash_table_lookup(rtpe_signalling_templates, &s); if (!tplate) { @@ -2136,6 +2169,11 @@ static void ng_media_free(struct ng_media *m) { g_free(m); } +static void ng_tag_free(struct ng_tag *tag) { + t_queue_clear_full(&tag->to, str_free); + g_free(tag); +} + void call_ng_free_flags(sdp_ng_flags *flags) { str_case_value_ht_destroy_ptr(&flags->codec_set); if (flags->frequencies) @@ -2158,4 +2196,6 @@ RTPE_NG_FLAGS_STR_CASE_HT_PARAMS t_queue_clear_full(&flags->medias, ng_media_free); t_queue_clear(&flags->groups_other); + + t_queue_clear_full(&flags->tags, ng_tag_free); } diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 17281ffe4..391d538a5 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1423,7 +1423,6 @@ static const char *medias_match(call_q *calls, medias_q *medias, if (!calls->length) return "Unknown call-ID(s)"; - call_t *call = calls->head->data; if (flags->all == ALL_ALL) { @@ -2575,6 +2574,73 @@ const char *call_create_answer_ng(ng_command_ctx_t *ctx) { } +const char *call_mesh_ng(ng_command_ctx_t *ctx) { + g_auto(sdp_ng_flags) flags; + + call_ng_process_flags_RETURN(&flags, ctx); + + g_auto(call_q) calls = calls_get(&flags.calls); + if (!calls.length) + return "Unknown call ID(s)"; + + g_autoptr(call_t) call = calls_merge(&calls); + if (!call) + return "Failed to merge calls (tag collision)"; + + g_auto(medias_q) upd_src_medias = TYPED_GQUEUE_INIT; + g_auto(medias_q) upd_dst_medias = TYPED_GQUEUE_INIT; + g_auto(medias_q) unconf_medias = TYPED_GQUEUE_INIT; + + if (!flags.tags.length) + goto out; + + // first pass + for (auto_iter(l, flags.tags.head); l; l = l->next) { + __auto_type tag = l->data; + tag->from_ml = call_get_monologue(call, &tag->from); + if (!tag->from_ml) + return "Given from-tag not found"; + + if (flags.unsubscribe) { + unsubscribe_monologue_from_all(tag->from_ml); + if (flags.bidirectional) + unsubscribe_all_from_monologue(tag->from_ml); + } + } + + // second pass + for (auto_iter(l, flags.tags.head); l; l = l->next) { + __auto_type tag = l->data; + __auto_type from_ml = tag->from_ml; + g_auto(medias_q) medias = TYPED_GQUEUE_INIT; + + for (unsigned int i = 0; i < from_ml->medias->len; i++) { + __auto_type media = from_ml->medias->pdata[i]; + if (!media) + continue; + t_queue_push_tail(&medias, media); + } + + for (auto_iter(k, tag->to.head); k; k = k->next) { + __auto_type to_s = k->data; + __auto_type to_ml = call_get_monologue(call, to_s); + if (!to_ml) + return "Given to-tag not found"; + + subscriber_connect(&medias, to_ml, &flags, true, &upd_src_medias, + &upd_dst_medias, &unconf_medias); + } + } + + subscriber_connect_finish(&upd_src_medias, &upd_dst_medias, &unconf_medias, &flags); + +out: + call_unlock_release_update(&call); + + return NULL; +} + + void call_interfaces_free(void) { if (info_re) { pcre2_code_free(info_re); diff --git a/daemon/control_ng.c b/daemon/control_ng.c index b29989417..71151be6d 100644 --- a/daemon/control_ng.c +++ b/daemon/control_ng.c @@ -49,7 +49,7 @@ const char *ng_command_strings[OP_COUNT] = { "subscribe answer", "unsubscribe", "inject start", "inject stop", "connect", "cli", "transform", - "create", "create answer", + "create", "create answer", "mesh", }; const char *ng_command_strings_esc[OP_COUNT] = { "ping", "offer", "answer", "delete", "query", "list", @@ -62,7 +62,7 @@ const char *ng_command_strings_esc[OP_COUNT] = { "subscribe_answer", "unsubscribe", "inject_start", "inject_stop", "connect", "cli", "transform", - "create", "create_answer", + "create", "create_answer", "mesh", }; const char *ng_command_strings_short[OP_COUNT] = { "Ping", "Offer", "Answer", "Delete", "Query", "List", @@ -74,7 +74,7 @@ const char *ng_command_strings_short[OP_COUNT] = { "Pub", "SubReq", "SubAns", "Unsub", "InjStart", "InjStop", "Conn", "CLI", "Trnsfm", - "Create", "CrtAnsw", + "Create", "CrtAnsw", "Mesh", }; typedef struct ng_ctx { @@ -893,6 +893,10 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons command_ctx.opmode = OP_CREATE_ANSWER; errstr = call_create_answer_ng(&command_ctx); break; + case CSH_LOOKUP("mesh"): + command_ctx.opmode = OP_MESH; + errstr = call_mesh_ng(&command_ctx); + break; default: errstr = "Unrecognized command"; } diff --git a/docs/ng_control_protocol.md b/docs/ng_control_protocol.md index 7721486ed..2edeeeddc 100644 --- a/docs/ng_control_protocol.md +++ b/docs/ng_control_protocol.md @@ -68,6 +68,7 @@ Currently the following commands are defined: * connect * create * create answer +* mesh The response dictionary must contain at least one key called `result`. The value can be either `ok` or `error`. @@ -2777,3 +2778,26 @@ The corresponding answer SDP (i.e. the answer received to the SDP returned by `create`) can then be passed to *rtpengine* as a `create answer` message. The SDP must be placed as `sdp` in the message, and the keys `call-id` and `from-tag` must be filled appropriated. + +## `mesh` Message + +This method can be used to merge an arbitrary number of separate calls into +one, and/or to establish arbitrary media flows between parties to a call. + +The request dictionary must include the key `calls` containing a list of +strings. Each string identifies an existing call by call ID. At least one call +must be given. If multiple calls are given, they will be merged into one, and +all call IDs will become aliases to that one call. + +The optional key `tags` contains a list of dictionary, each in the format of +`{from=STRING, to=[STRING, STRING, ...]}`. Each string identifies a party to +the (possibly merged) call by its tag. This establishes media flow from each +given `from` call party to each one of the `to` call parties. + +Other dictionary keys and the `flags` list are honoured as usual. The flag +`unsubscribe` can be given to reset the media subscriptions for each given +`from` call party before establishing the new media flows. The flag +`bidirectional` can be given to establish (and also reset) media flows in both +directions for each given pair. + +To facilitate audio mixing, see the `audio player` options described above. diff --git a/include/call_flags.h b/include/call_flags.h index 29c9d0c21..af99066df 100644 --- a/include/call_flags.h +++ b/include/call_flags.h @@ -23,9 +23,19 @@ struct ng_media { }; +struct ng_tag { + str from; + str_q to; + + struct call_monologue *from_ml; +}; + +TYPED_GQUEUE(tags, struct ng_tag) + #define RTPE_NG_FLAGS_STR_Q_PARAMS \ X(from_tags) \ + X(calls) \ X(codec_strip) \ X(codec_ignore) \ X(codec_offer) \ @@ -181,6 +191,7 @@ struct sdp_ng_flags { str vsc_pause_resume_rec; str vsc_start_pause_resume_rec; int t38_version; + tags_q tags; #define X(x) str_q x; RTPE_NG_FLAGS_STR_Q_PARAMS @@ -299,6 +310,7 @@ RTPE_NG_FLAGS_STR_CASE_HT_PARAMS pierce_nat:1, directional:1, bidirectional:1, + unsubscribe:1, fatal:1, new_branch:1, provisional:1, diff --git a/include/call_interfaces.h b/include/call_interfaces.h index 6e652b07b..33233f444 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -59,6 +59,7 @@ const char *call_connect_ng(ng_command_ctx_t *); const char *call_transform_ng(ng_command_ctx_t *); const char *call_create_ng(ng_command_ctx_t *); const char *call_create_answer_ng(ng_command_ctx_t *); +const char *call_mesh_ng(ng_command_ctx_t *); int call_interfaces_init(charp_ht); void call_interfaces_free(void); diff --git a/include/control_ng.h b/include/control_ng.h index ec8d197f1..800fe3d7d 100644 --- a/include/control_ng.h +++ b/include/control_ng.h @@ -36,6 +36,7 @@ enum ng_opmode { OP_TRANSFORM, OP_CREATE, OP_CREATE_ANSWER, + OP_MESH, OP_COUNT, // last, number of elements OP_OTHER = OP_COUNT // alias to above @@ -94,9 +95,11 @@ typedef union { struct ng_media *media; struct ng_codec *codec; struct rtp_payload_type *pt; + struct ng_tag *tag; void *generic; } helper_arg __attribute__ ((__transparent_union__)); + struct ng_parser { void (*init)(ng_parser_ctx_t *, bencode_buffer_t *); str (*collapse)(ng_parser_ctx_t *, parser_arg, void **); diff --git a/t/auto-daemon-tests-create.pl b/t/auto-daemon-tests-create.pl index 9ea35bb30..0fb5839d6 100755 --- a/t/auto-daemon-tests-create.pl +++ b/t/auto-daemon-tests-create.pl @@ -3503,5 +3503,1256 @@ SDP +($sock_a, $sock_b) = new_call([qw(198.51.100.11 4070)], [qw(198.51.100.11 4072)]); + +($port_a) = offer('full mesh', { }, < [], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [$tt, ft(), tt()], + }, + { + from => $tt, + to => [$ft, ft(), tt()], + }, + { + from => ft(), + to => [$ft, $tt, tt()], + }, + { + from => tt(), + to => [$ft, $tt, ft()], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1001, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1001, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1001, 3160, 0x1234, "\x11" x 160)); +rcv($sock_d, $port_c, rtpm(0, 1001, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3001, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3001, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_c, $port_d, rtpm(0, 3001, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3001, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5001, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5001, 7160, 0x1234, "\x33" x 160)); +rcv($sock_b, $port_a, rtpm(0, 5001, 7160, 0x1234, "\x33" x 160)); +rcv($sock_a, $port_b, rtpm(0, 5001, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7001, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7001, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_b, $port_a, rtpm(0, 7001, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_a, $port_b, rtpm(0, 7001, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +rtpe_req('mesh', 'full mesh', { + flags => [], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [$tt, ft(), tt()], + }, + { + from => $tt, + to => [$ft, ft(), tt()], + }, + { + from => ft(), + to => [$ft, $tt, tt()], + }, + { + from => tt(), + to => [$ft, $tt, ft()], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1002, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1002, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1002, 3160, 0x1234, "\x11" x 160)); +rcv($sock_d, $port_c, rtpm(0, 1002, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3002, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3002, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_c, $port_d, rtpm(0, 3002, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3002, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5002, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5002, 7160, 0x1234, "\x33" x 160)); +rcv($sock_b, $port_a, rtpm(0, 5002, 7160, 0x1234, "\x33" x 160)); +rcv($sock_a, $port_b, rtpm(0, 5002, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7002, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7002, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_b, $port_a, rtpm(0, 7002, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_a, $port_b, rtpm(0, 7002, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +rtpe_req('mesh', 'full mesh', { + flags => ['unsubscribe'], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [$tt, ft(), tt()], + }, + { + from => $tt, + to => [$ft, ft(), tt()], + }, + { + from => ft(), + to => [$ft, $tt, tt()], + }, + { + from => tt(), + to => [$ft, $tt, ft()], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1003, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1003, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1003, 3160, 0x1234, "\x11" x 160)); +rcv($sock_d, $port_c, rtpm(0, 1003, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3003, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3003, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_c, $port_d, rtpm(0, 3003, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3003, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5003, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5003, 7160, 0x1234, "\x33" x 160)); +rcv($sock_b, $port_a, rtpm(0, 5003, 7160, 0x1234, "\x33" x 160)); +rcv($sock_a, $port_b, rtpm(0, 5003, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7003, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7003, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_b, $port_a, rtpm(0, 7003, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_a, $port_b, rtpm(0, 7003, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +rtpe_req('mesh', 'full mesh', { + flags => [], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [$tt], + }, + { + from => $tt, + to => [$ft], + }, + { + from => ft(), + to => [tt()], + }, + { + from => tt(), + to => [ft()], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1004, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1004, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1004, 3160, 0x1234, "\x11" x 160)); +rcv($sock_d, $port_c, rtpm(0, 1004, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3004, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3004, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_c, $port_d, rtpm(0, 3004, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3004, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5004, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5004, 7160, 0x1234, "\x33" x 160)); +rcv($sock_b, $port_a, rtpm(0, 5004, 7160, 0x1234, "\x33" x 160)); +rcv($sock_a, $port_b, rtpm(0, 5004, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7004, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7004, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_b, $port_a, rtpm(0, 7004, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_a, $port_b, rtpm(0, 7004, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +# reset to original +rtpe_req('mesh', 'full mesh', { + flags => ['unsubscribe'], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [$tt], + }, + { + from => $tt, + to => [$ft], + }, + { + from => ft(), + to => [tt()], + }, + { + from => tt(), + to => [ft()], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1005, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1005, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3005, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3005, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5005, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5005, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7005, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7005, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + + +($sock_a, $sock_b) = new_call([qw(198.51.100.12 4070)], [qw(198.51.100.12 4072)]); + +($port_a) = offer('directional mesh', { }, < [], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [ft()], + }, + { + from => $tt, + to => [tt()], + }, + { + from => ft(), + to => [], + }, + { + from => tt(), + to => [], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1001, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1001, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1001, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3001, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3001, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3001, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5001, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5001, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7001, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7001, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +rtpe_req('mesh', 'directional mesh', { + flags => [], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [ft()], + }, + { + from => $tt, + to => [tt()], + }, + { + from => ft(), + to => [], + }, + { + from => tt(), + to => [], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1002, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1002, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1002, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3002, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3002, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3002, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5002, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5002, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7002, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7002, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +rtpe_req('mesh', 'directional mesh', { + flags => ['unsubscribe'], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [ft()], + }, + { + from => $tt, + to => [tt()], + }, + { + from => ft(), + to => [], + }, + { + from => tt(), + to => [], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1003, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1003, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3003, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3003, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5003, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7003, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +rtpe_req('mesh', 'directional mesh', { + flags => [], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [$tt], + }, + { + from => $tt, + to => [$ft], + }, + { + from => ft(), + to => [tt()], + }, + { + from => tt(), + to => [ft()], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1004, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1004, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1004, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3004, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3004, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3004, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5004, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5004, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7004, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7004, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +# reset to original +rtpe_req('mesh', 'directional mesh', { + flags => ['unsubscribe'], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [$tt], + }, + { + from => $tt, + to => [$ft], + }, + { + from => ft(), + to => [tt()], + }, + { + from => tt(), + to => [ft()], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1005, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1005, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3005, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3005, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5005, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5005, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7005, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7005, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + + + + + + + + + + + + + +($sock_a, $sock_b) = new_call([qw(198.51.100.13 4070)], [qw(198.51.100.13 4072)]); + +($port_a) = offer('bidirectional mesh', { }, < ['bidirectional'], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [ft()], + }, + { + from => $tt, + to => [tt()], + }, + { + from => ft(), + to => [], + }, + { + from => tt(), + to => [], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1001, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1001, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1001, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3001, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3001, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3001, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5001, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5001, 7160, 0x1234, "\x33" x 160)); +rcv($sock_a, $port_b, rtpm(0, 5001, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7001, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7001, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_b, $port_a, rtpm(0, 7001, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +rtpe_req('mesh', 'bidirectional mesh', { + flags => ['bidirectional'], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [ft()], + }, + { + from => $tt, + to => [tt()], + }, + { + from => ft(), + to => [], + }, + { + from => tt(), + to => [], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1002, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1002, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1002, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3002, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3002, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3002, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5002, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5002, 7160, 0x1234, "\x33" x 160)); +rcv($sock_a, $port_b, rtpm(0, 5002, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7002, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7002, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_b, $port_a, rtpm(0, 7002, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +rtpe_req('mesh', 'bidirectional mesh', { + flags => ['unsubscribe', 'bidirectional'], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [ft()], + }, + { + from => $tt, + to => [tt()], + }, + { + from => ft(), + to => [], + }, + { + from => tt(), + to => [], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1003, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1003, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3003, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3003, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5003, 7160, 0x1234, "\x33" x 160)); +rcv($sock_a, $port_b, rtpm(0, 5003, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7003, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_b, $port_a, rtpm(0, 7003, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +rtpe_req('mesh', 'bidirectional mesh', { + flags => ['bidirectional'], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [$tt], + }, + { + from => $tt, + to => [$ft], + }, + { + from => ft(), + to => [tt()], + }, + { + from => tt(), + to => [ft()], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1004, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1004, 3160, 0x1234, "\x11" x 160)); +rcv($sock_c, $port_d, rtpm(0, 1004, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3004, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3004, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_d, $port_c, rtpm(0, 3004, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5004, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5004, 7160, 0x1234, "\x33" x 160)); +rcv($sock_a, $port_b, rtpm(0, 5004, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7004, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7004, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_b, $port_a, rtpm(0, 7004, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +# reset to original +rtpe_req('mesh', 'bidirectional mesh', { + flags => ['unsubscribe', 'bidirectional'], + calls => [cid(), $cid1], + tags => [ + { + from => $ft, + to => [$tt], + }, + { + from => $tt, + to => [], + }, + { + from => ft(), + to => [tt()], + }, + { + from => tt(), + to => [], + }, + ], +}); + + +snd($sock_a, $port_b, rtp (0, 1005, 3160, 0x1234, "\x11" x 160)); +rcv($sock_b, $port_a, rtpm(0, 1005, 3160, 0x1234, "\x11" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_b, $port_a, rtp (0, 3005, 5160, 0x1a04, "\x22" x 160)); +rcv($sock_a, $port_b, rtpm(0, 3005, 5160, 0x1a04, "\x22" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + +snd($sock_c, $port_d, rtp (0, 5005, 7160, 0x1234, "\x33" x 160)); +rcv($sock_d, $port_c, rtpm(0, 5005, 7160, 0x1234, "\x33" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + +snd($sock_d, $port_c, rtp (0, 7005, 9160, 0x1a04, "\x44" x 160)); +rcv($sock_c, $port_d, rtpm(0, 7005, 9160, 0x1a04, "\x44" x 160)); +rcv_no($sock_a); +rcv_no($sock_b); +rcv_no($sock_c); +rcv_no($sock_d); + + + + + + + + + + done_testing(); #done_testing;NGCP::Rtpengine::AutoTest::terminate('f00');exit; diff --git a/t/test-stats.c b/t/test-stats.c index 21f85a523..6499c49d9 100644 --- a/t/test-stats.c +++ b/t/test-stats.c @@ -329,6 +329,13 @@ int main(void) { "create_answers_ps_max 0 150\n" "create_answers_ps_avg 0 150\n" "create_answer_count 0 150\n" + "mesh_time_min 0.000000 150\n" + "mesh_time_max 0.000000 150\n" + "mesh_time_avg 0.000000 150\n" + "meshs_ps_min 0 150\n" + "meshs_ps_max 0 150\n" + "meshs_ps_avg 0 150\n" + "mesh_count 0 150\n" "call_dur 0.000000 150\n" "average_call_dur 0.000000 150\n" "forced_term_sess 0 150\n" @@ -851,6 +858,14 @@ int main(void) { "0.000000\n" "avgcreate answerdelay\n" "0.000000\n" + "Min/Max/Avg mesh processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "minmeshdelay\n" + "0.000000\n" + "maxmeshdelay\n" + "0.000000\n" + "avgmeshdelay\n" + "0.000000\n" "Min/Max/Avg ping requests per second\n" "0/0/0 per sec\n" "minpingrequestrate\n" @@ -1123,6 +1138,14 @@ int main(void) { "0\n" "avgcreate answerrequestrate\n" "0\n" + "Min/Max/Avg mesh requests per second\n" + "0/0/0 per sec\n" + "minmeshrequestrate\n" + "0\n" + "maxmeshrequestrate\n" + "0\n" + "avgmeshrequestrate\n" + "0\n" "\n" "\n" "}\n" @@ -1286,7 +1309,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 | InjStart | InjStop | Conn | CLI | Trnsfm | Create | CrtAnsw \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 | Create | CrtAnsw | Mesh \n" "\n" "]\n" "totalpingcount\n" @@ -1357,6 +1380,8 @@ int main(void) { "0\n" "totalcrtanswcount\n" "0\n" + "totalmeshcount\n" + "0\n" "\n" "}\n" "interfaces\n" @@ -1616,6 +1641,13 @@ int main(void) { "create_answers_ps_max 0 150\n" "create_answers_ps_avg 0 150\n" "create_answer_count 0 150\n" + "mesh_time_min 0.000000 150\n" + "mesh_time_max 0.000000 150\n" + "mesh_time_avg 0.000000 150\n" + "meshs_ps_min 0 150\n" + "meshs_ps_max 0 150\n" + "meshs_ps_avg 0 150\n" + "mesh_count 0 150\n" "call_dur 0.000000 150\n" "average_call_dur 0.000000 150\n" "forced_term_sess 0 150\n" @@ -2138,6 +2170,14 @@ int main(void) { "0.000000\n" "avgcreate answerdelay\n" "0.000000\n" + "Min/Max/Avg mesh processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "minmeshdelay\n" + "0.000000\n" + "maxmeshdelay\n" + "0.000000\n" + "avgmeshdelay\n" + "0.000000\n" "Min/Max/Avg ping requests per second\n" "0/0/0 per sec\n" "minpingrequestrate\n" @@ -2410,6 +2450,14 @@ int main(void) { "0\n" "avgcreate answerrequestrate\n" "0\n" + "Min/Max/Avg mesh requests per second\n" + "0/0/0 per sec\n" + "minmeshrequestrate\n" + "0\n" + "maxmeshrequestrate\n" + "0\n" + "avgmeshrequestrate\n" + "0\n" "\n" "\n" "}\n" @@ -2573,7 +2621,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 | InjStart | InjStop | Conn | CLI | Trnsfm | Create | CrtAnsw \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 | Create | CrtAnsw | Mesh \n" "\n" "]\n" "totalpingcount\n" @@ -2644,6 +2692,8 @@ int main(void) { "0\n" "totalcrtanswcount\n" "0\n" + "totalmeshcount\n" + "0\n" "\n" "}\n" "interfaces\n" @@ -2900,6 +2950,13 @@ int main(void) { "create_answers_ps_max 0 150\n" "create_answers_ps_avg 0 150\n" "create_answer_count 0 150\n" + "mesh_time_min 0.000000 150\n" + "mesh_time_max 0.000000 150\n" + "mesh_time_avg 0.000000 150\n" + "meshs_ps_min 0 150\n" + "meshs_ps_max 0 150\n" + "meshs_ps_avg 0 150\n" + "mesh_count 0 150\n" "call_dur 0.000000 150\n" "average_call_dur 0.000000 150\n" "forced_term_sess 0 150\n" @@ -3422,6 +3479,14 @@ int main(void) { "0.000000\n" "avgcreate answerdelay\n" "0.000000\n" + "Min/Max/Avg mesh processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "minmeshdelay\n" + "0.000000\n" + "maxmeshdelay\n" + "0.000000\n" + "avgmeshdelay\n" + "0.000000\n" "Min/Max/Avg ping requests per second\n" "0/0/0 per sec\n" "minpingrequestrate\n" @@ -3694,6 +3759,14 @@ int main(void) { "0\n" "avgcreate answerrequestrate\n" "0\n" + "Min/Max/Avg mesh requests per second\n" + "0/0/0 per sec\n" + "minmeshrequestrate\n" + "0\n" + "maxmeshrequestrate\n" + "0\n" + "avgmeshrequestrate\n" + "0\n" "\n" "\n" "}\n" @@ -3857,7 +3930,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 | InjStart | InjStop | Conn | CLI | Trnsfm | Create | CrtAnsw \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 | Create | CrtAnsw | Mesh \n" "\n" "]\n" "totalpingcount\n" @@ -3928,6 +4001,8 @@ int main(void) { "0\n" "totalcrtanswcount\n" "0\n" + "totalmeshcount\n" + "0\n" "\n" "}\n" "interfaces\n" @@ -4203,6 +4278,13 @@ int main(void) { "create_answers_ps_max 0 157\n" "create_answers_ps_avg 0 157\n" "create_answer_count 0 157\n" + "mesh_time_min 0.000000 157\n" + "mesh_time_max 0.000000 157\n" + "mesh_time_avg 0.000000 157\n" + "meshs_ps_min 0 157\n" + "meshs_ps_max 0 157\n" + "meshs_ps_avg 0 157\n" + "mesh_count 0 157\n" "call_dur 0.000000 157\n" "average_call_dur 0.000000 157\n" "forced_term_sess 0 157\n" @@ -4725,6 +4807,14 @@ int main(void) { "0.000000\n" "avgcreate answerdelay\n" "0.000000\n" + "Min/Max/Avg mesh processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "minmeshdelay\n" + "0.000000\n" + "maxmeshdelay\n" + "0.000000\n" + "avgmeshdelay\n" + "0.000000\n" "Min/Max/Avg ping requests per second\n" "0/0/0 per sec\n" "minpingrequestrate\n" @@ -4997,6 +5087,14 @@ int main(void) { "0\n" "avgcreate answerrequestrate\n" "0\n" + "Min/Max/Avg mesh requests per second\n" + "0/0/0 per sec\n" + "minmeshrequestrate\n" + "0\n" + "maxmeshrequestrate\n" + "0\n" + "avgmeshrequestrate\n" + "0\n" "\n" "\n" "}\n" @@ -5160,7 +5258,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 | InjStart | InjStop | Conn | CLI | Trnsfm | Create | CrtAnsw \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 | Create | CrtAnsw | Mesh \n" "\n" "]\n" "totalpingcount\n" @@ -5231,6 +5329,8 @@ int main(void) { "0\n" "totalcrtanswcount\n" "0\n" + "totalmeshcount\n" + "0\n" "\n" "}\n" "interfaces\n" @@ -5495,6 +5595,13 @@ int main(void) { "create_answers_ps_max 0 157\n" "create_answers_ps_avg 0 157\n" "create_answer_count 0 157\n" + "mesh_time_min 0.000000 157\n" + "mesh_time_max 0.000000 157\n" + "mesh_time_avg 0.000000 157\n" + "meshs_ps_min 0 157\n" + "meshs_ps_max 0 157\n" + "meshs_ps_avg 0 157\n" + "mesh_count 0 157\n" "call_dur 0.000000 157\n" "average_call_dur 0.000000 157\n" "forced_term_sess 0 157\n" @@ -6017,6 +6124,14 @@ int main(void) { "0.000000\n" "avgcreate answerdelay\n" "0.000000\n" + "Min/Max/Avg mesh processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "minmeshdelay\n" + "0.000000\n" + "maxmeshdelay\n" + "0.000000\n" + "avgmeshdelay\n" + "0.000000\n" "Min/Max/Avg ping requests per second\n" "0/0/0 per sec\n" "minpingrequestrate\n" @@ -6289,6 +6404,14 @@ int main(void) { "0\n" "avgcreate answerrequestrate\n" "0\n" + "Min/Max/Avg mesh requests per second\n" + "0/0/0 per sec\n" + "minmeshrequestrate\n" + "0\n" + "maxmeshrequestrate\n" + "0\n" + "avgmeshrequestrate\n" + "0\n" "\n" "\n" "}\n" @@ -6452,7 +6575,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 | InjStart | InjStop | Conn | CLI | Trnsfm | Create | CrtAnsw \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 | Create | CrtAnsw | Mesh \n" "\n" "]\n" "totalpingcount\n" @@ -6523,6 +6646,8 @@ int main(void) { "0\n" "totalcrtanswcount\n" "0\n" + "totalmeshcount\n" + "0\n" "\n" "}\n" "interfaces\n" @@ -6781,6 +6906,13 @@ int main(void) { "create_answers_ps_max 0 200\n" "create_answers_ps_avg 0 200\n" "create_answer_count 0 200\n" + "mesh_time_min 0.000000 200\n" + "mesh_time_max 0.000000 200\n" + "mesh_time_avg 0.000000 200\n" + "meshs_ps_min 0 200\n" + "meshs_ps_max 0 200\n" + "meshs_ps_avg 0 200\n" + "mesh_count 0 200\n" "call_dur 143.000000 200\n" "average_call_dur 0.000000 200\n" "forced_term_sess 0 200\n" @@ -7303,6 +7435,14 @@ int main(void) { "0.000000\n" "avgcreate answerdelay\n" "0.000000\n" + "Min/Max/Avg mesh processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "minmeshdelay\n" + "0.000000\n" + "maxmeshdelay\n" + "0.000000\n" + "avgmeshdelay\n" + "0.000000\n" "Min/Max/Avg ping requests per second\n" "0/0/0 per sec\n" "minpingrequestrate\n" @@ -7575,6 +7715,14 @@ int main(void) { "0\n" "avgcreate answerrequestrate\n" "0\n" + "Min/Max/Avg mesh requests per second\n" + "0/0/0 per sec\n" + "minmeshrequestrate\n" + "0\n" + "maxmeshrequestrate\n" + "0\n" + "avgmeshrequestrate\n" + "0\n" "\n" "\n" "}\n" @@ -7738,7 +7886,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 | InjStart | InjStop | Conn | CLI | Trnsfm | Create | CrtAnsw \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 | Create | CrtAnsw | Mesh \n" "\n" "]\n" "totalpingcount\n" @@ -7809,6 +7957,8 @@ int main(void) { "0\n" "totalcrtanswcount\n" "0\n" + "totalmeshcount\n" + "0\n" "\n" "}\n" "interfaces\n" @@ -8070,6 +8220,13 @@ int main(void) { "create_answers_ps_max 0 200\n" "create_answers_ps_avg 0 200\n" "create_answer_count 0 200\n" + "mesh_time_min 0.000000 200\n" + "mesh_time_max 0.000000 200\n" + "mesh_time_avg 0.000000 200\n" + "meshs_ps_min 0 200\n" + "meshs_ps_max 0 200\n" + "meshs_ps_avg 0 200\n" + "mesh_count 0 200\n" "call_dur 0.000000 200\n" "average_call_dur 93.000000 200\n" "forced_term_sess 0 200\n" @@ -8592,6 +8749,14 @@ int main(void) { "0.000000\n" "avgcreate answerdelay\n" "0.000000\n" + "Min/Max/Avg mesh processing delay\n" + "0.000000/0.000000/0.000000 sec\n" + "minmeshdelay\n" + "0.000000\n" + "maxmeshdelay\n" + "0.000000\n" + "avgmeshdelay\n" + "0.000000\n" "Min/Max/Avg ping requests per second\n" "0/0/0 per sec\n" "minpingrequestrate\n" @@ -8864,6 +9029,14 @@ int main(void) { "0\n" "avgcreate answerrequestrate\n" "0\n" + "Min/Max/Avg mesh requests per second\n" + "0/0/0 per sec\n" + "minmeshrequestrate\n" + "0\n" + "maxmeshrequestrate\n" + "0\n" + "avgmeshrequestrate\n" + "0\n" "\n" "\n" "}\n" @@ -9027,7 +9200,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 | InjStart | InjStop | Conn | CLI | Trnsfm | Create | CrtAnsw \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 | Create | CrtAnsw | Mesh \n" "\n" "]\n" "totalpingcount\n" @@ -9098,6 +9271,8 @@ int main(void) { "0\n" "totalcrtanswcount\n" "0\n" + "totalmeshcount\n" + "0\n" "\n" "}\n" "interfaces\n" diff --git a/utils/rtpengine-ng-client b/utils/rtpengine-ng-client index 2ec111554..546655cc8 100755 --- a/utils/rtpengine-ng-client +++ b/utils/rtpengine-ng-client @@ -58,6 +58,7 @@ my @flags = qw( allow-no-codec-media bidirectional mix + unsubscribe ); my @string_opts = qw(