[Asterisk-code-review] res_rtp_asterisk: Add a DEVMODE RTP drop packets CLI command (asterisk[16])
Kevin Harwell
asteriskteam at digium.com
Fri Mar 5 13:03:08 CST 2021
Kevin Harwell has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/15592 )
Change subject: res_rtp_asterisk: Add a DEVMODE RTP drop packets CLI command
......................................................................
res_rtp_asterisk: Add a DEVMODE RTP drop packets CLI command
This patch makes it so when Asterisk is compiled in DEVMODE a CLI
command is available that allows someone to drop incoming RTP
packets. The command allows for dropping of packets once, or on a
timed interval (e.g. drop 10 packets every 5 seconds). A user can
also specify to drop packets by IP address.
Change-Id: I25fa7ae9bad6ed68e273bbcccf0ee51cae6e7024
---
M res/res_rtp_asterisk.c
1 file changed, 171 insertions(+), 0 deletions(-)
git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/92/15592/1
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index a962d70..8d89a53 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -63,6 +63,7 @@
#include <ifaddrs.h>
#endif
+#include "asterisk/conversions.h"
#include "asterisk/options.h"
#include "asterisk/logger_category.h"
#include "asterisk/stun.h"
@@ -7489,6 +7490,55 @@
return AST_LIST_FIRST(&frames);
}
+#ifdef AST_DEVMODE
+
+struct rtp_drop_packets_data {
+ unsigned int num_to_drop;
+ unsigned int num_dropped;
+ struct timeval interval;
+ struct timeval next;
+ struct ast_sockaddr addr;
+ unsigned int port;
+} drop_packets_data;
+
+static int should_drop_packets(struct ast_sockaddr *addr)
+{
+ struct timeval tv;
+
+ if (!drop_packets_data.num_to_drop) {
+ return 0;
+ }
+
+ if (!ast_sockaddr_isnull(&drop_packets_data.addr) &&
+ (drop_packets_data.port ?
+ ast_sockaddr_cmp(&drop_packets_data.addr, addr) :
+ ast_sockaddr_cmp_addr(&drop_packets_data.addr, addr)) != 0) {
+ return 0;
+ }
+
+ if (drop_packets_data.num_dropped < drop_packets_data.num_to_drop) {
+ ++drop_packets_data.num_dropped;
+ return 1;
+ }
+
+ if (ast_tvzero(drop_packets_data.interval)) {
+ /* If no interval then drop specified number of packets and be done */
+ drop_packets_data.num_to_drop = 0;
+ return 0;
+ }
+
+ tv = ast_tvnow();
+ if (ast_tvcmp(tv, drop_packets_data.next) == -1) {
+ return 0;
+ }
+
+ drop_packets_data.num_dropped = 0;
+ drop_packets_data.next = ast_tvadd(tv, drop_packets_data.interval);
+ return 1;
+}
+
+#endif
+
/*! \pre instance is locked */
static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
{
@@ -7783,6 +7833,14 @@
seqno &= 0xffff;
timestamp = ntohl(rtpheader[1]);
+#ifdef AST_DEVMODE
+ if (should_drop_packets(&addr)) {
+ ast_debug(0, "(%p) RTP: drop received packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d)\n",
+ instance, ast_sockaddr_stringify(&addr), payloadtype, seqno, timestamp, res - hdrlen);
+ return &ast_null_frame;
+ }
+#endif
+
if (rtp_debug_test_addr(&addr)) {
ast_verbose("Got RTP packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d)\n",
ast_sockaddr_stringify(&addr),
@@ -9070,11 +9128,124 @@
return CLI_SUCCESS;
}
+#ifdef AST_DEVMODE
+
+static char *handle_cli_rtp_drop_packets(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ static const char * const completions_2[] = { "stop", "<N>", NULL };
+ static const char * const completions_3[] = { "incoming packets", NULL };
+ static const char * const completions_5[] = { "every", "on", NULL };
+ static const char * const completions_units[] = { "usec", "msec", "sec", "min", NULL };
+
+ unsigned int num_to_drop = 0;
+ unsigned int interval = 0;
+ const char *interval_s = NULL;
+ const char *unit_s = NULL;
+ struct ast_sockaddr addr;
+ const char *addr_s = NULL;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rtp drop";
+ e->usage =
+ "Usage: rtp drop [stop|[<N> incoming packets[ every <N> {usec|msec|sec|min}]][ on <ip[:port]>]\n"
+ " Drop RTP packets.\n";
+ return NULL;
+ case CLI_GENERATE:
+ switch (a->pos) {
+ case 2:
+ return ast_cli_complete(a->word, completions_2, a->n);
+ case 3:
+ return ast_cli_complete(a->word, completions_3, a->n);
+ case 5:
+ return ast_cli_complete(a->word, completions_5, a->n);
+ case 7:
+ if (!strcasecmp(a->argv[a->pos - 2], "on")) {
+ ast_cli_completion_add(ast_strdup("every"));
+ break;
+ }
+ case 9:
+ if (!strcasecmp(a->argv[a->pos - 2], "every")) {
+ return ast_cli_complete(a->word, completions_units, a->n);
+ }
+ break;
+ case 8:
+ if (strcasecmp(a->argv[a->pos - 1], "every")) {
+ ast_cli_completion_add(ast_strdup("on"));
+ }
+ break;
+ }
+
+ return NULL;
+ }
+
+ if (a->argc < 3) {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (!strcasecmp(a->argv[2], "stop")) {
+ /* rtp drop stop */
+ } else if (a->argc < 5) {
+ return CLI_SHOWUSAGE;
+ } else if (ast_str_to_uint(a->argv[2], &num_to_drop)) {
+ ast_cli(a->fd, "%s is not a valid number of packets to drop\n", a->argv[2]);
+ return CLI_FAILURE;
+ } else if (a->argc == 5) {
+ /* rtp drop <N> incoming packets */
+ } else if (a->argc >= 7 && !strcasecmp(a->argv[5], "on")) {
+ /* rtp drop <N> incoming packets on <ip[:port]> */
+ addr_s = a->argv[6];
+ if (a->argc == 10 && !strcasecmp(a->argv[7], "every")) {
+ /* rtp drop <N> incoming packets on <ip[:port]> every <N> {usec|msec|sec|min}*/
+ interval_s = a->argv[8];
+ unit_s = a->argv[9];
+ }
+ } else if (a->argc >= 8 && !strcasecmp(a->argv[5], "every")) {
+ /* rtp drop <N> incoming packets every <N> {usec|msec|sec|min}*/
+ interval_s = a->argv[6];
+ unit_s = a->argv[7];
+ if (a->argc == 10 && !strcasecmp(a->argv[8], "on")) {
+ /* rtp drop <N> incoming packets every <N> {usec|msec|sec|min} on <ip[:port]>*/
+ addr_s = a->argv[9];
+ }
+ } else {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (a->argc == 8 || a->argc == 9 || (a->argc >= 10 && (!interval_s || !addr_s))) {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (interval_s && ast_str_to_uint(interval_s, &interval)) {
+ ast_cli(a->fd, "%s is not a valid interval number\n", interval_s);
+ return CLI_FAILURE;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ if (addr_s && !ast_sockaddr_parse(&addr, addr_s, 0)) {
+ ast_cli(a->fd, "%s is not a valid hostname[:port]\n", addr_s);
+ return CLI_FAILURE;
+ }
+
+ drop_packets_data.num_to_drop = num_to_drop;
+ drop_packets_data.num_dropped = 0;
+ drop_packets_data.interval = ast_time_create_by_unit_str(interval, unit_s);
+ drop_packets_data.next = ast_tvnow();
+ ast_sockaddr_copy(&drop_packets_data.addr, &addr);
+ drop_packets_data.port = ast_sockaddr_port(&addr);
+
+ return CLI_SUCCESS;
+}
+#endif
+
static struct ast_cli_entry cli_rtp[] = {
AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
AST_CLI_DEFINE(handle_cli_rtp_settings, "Display RTP settings"),
AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
+#ifdef AST_DEVMODE
+ AST_CLI_DEFINE(handle_cli_rtp_drop_packets, "Drop RTP packets"),
+#endif
};
static int rtp_reload(int reload, int by_external_config)
--
To view, visit https://gerrit.asterisk.org/c/asterisk/+/15592
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings
Gerrit-Project: asterisk
Gerrit-Branch: 16
Gerrit-Change-Id: I25fa7ae9bad6ed68e273bbcccf0ee51cae6e7024
Gerrit-Change-Number: 15592
Gerrit-PatchSet: 1
Gerrit-Owner: Kevin Harwell <kharwell at digium.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20210305/c83a18de/attachment.html>
More information about the asterisk-code-review
mailing list