]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-9490: [mod_sofia] add filter to SIP messages that match a regexp.
authordavidcsi <david.villasmil.work@gmail.com>
Fri, 11 Nov 2016 01:55:38 +0000 (01:55 +0000)
committerMike Jerris <mike@jerris.com>
Fri, 11 Nov 2016 16:00:28 +0000 (10:00 -0600)
src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c

index 558663115203f1918a921b82b7c502d6c25da053..e66f99240c3d45c5fd20de7c351a52d7429fb8c7 100644 (file)
@@ -4179,6 +4179,10 @@ SWITCH_STANDARD_API(sofia_function)
        switch_status_t status = SWITCH_STATUS_SUCCESS;
        sofia_command_t func = NULL;
        int lead = 1;
+    const char *errorptr;
+    int erroffset;
+    const unsigned char *tables = 0;
+    uint32_t flags = 0;
        static const char usage_string[] = "USAGE:\n"
                "--------------------------------------------------------------------------------\n"
                "sofia global siptrace <on|off>\n"
@@ -4221,6 +4225,29 @@ SWITCH_STANDARD_API(sofia_function)
                func = cmd_status;
        } else if (!strcasecmp(argv[0], "xmlstatus")) {
                func = cmd_xml_status;
+       } else if (!strcasecmp(argv[0], "filter")) {
+           if (argc > 1) {
+               if (!strcasecmp(argv[1],"off")) {
+                   mod_sofia_globals.filtering = SWITCH_FALSE;
+                   switch_regex_free(mod_sofia_globals.filter_re);
+               } else {
+                       mod_sofia_globals.filtering = SWITCH_TRUE;
+                   strncpy( mod_sofia_globals.filter_expression, argv[1], sizeof(mod_sofia_globals.filter_expression) );
+                       mod_sofia_globals.filter_re = switch_regex_compile( argv[1], flags, &errorptr, &erroffset, tables );
+                       if (errorptr) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "COMPILE ERROR: %d [%s][%s]\n", erroffset, errorptr, argv[1]);
+                               stream->write_function(stream, "Couldn't compile that regex: %s\n", argv[1]);
+                               switch_regex_free(mod_sofia_globals.filter_re);
+                               goto done;
+                       }
+
+               }
+               stream->write_function(stream, "+OK %s filtering sofia log for %s\n", mod_sofia_globals.filtering ? "enabled" : "disabled", mod_sofia_globals.filter_expression );
+           } else {
+               stream->write_function(stream, "%s%s", "sofia filter is ", mod_sofia_globals.filtering ? "enabled. " : "disabled. ", mod_sofia_globals.filter_expression);
+               stream->write_function(stream, "%s", " (sofia filter <filter-regex|off>) - Enable, disable filtering, set 'filter-regex' to use as filter. Set 'filter-expression' to 'off' to stop filtering\n");
+           }
+        goto done;
        } else if (!strcasecmp(argv[0], "tracelevel")) {
                if (argv[1]) {
                        mod_sofia_globals.tracelevel = switch_log_str2level(argv[1]);
@@ -6109,7 +6136,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
        switch_console_set_complete("add sofia ::[help:status");
        switch_console_set_complete("add sofia status profile ::sofia::list_profiles reg");
        switch_console_set_complete("add sofia status gateway ::sofia::list_gateways");
-
+       switch_console_set_complete("add sofia filter");
        switch_console_set_complete("add sofia loglevel ::[all:default:tport:iptsec:nea:nta:nth_client:nth_server:nua:soa:sresolv:stun ::[0:1:2:3:4:5:6:7:8:9");
        switch_console_set_complete("add sofia tracelevel ::[console:alert:crit:err:warning:notice:info:debug");
 
index 5ed675dd20fe9e476319cc42731b248fade0e899..5f3b8f53a9d8509ac80e6046532c83918316951a 100644 (file)
@@ -155,6 +155,12 @@ typedef enum {
        SOFIA_CONFIG_RESPAWN
 } sofia_config_t;
 
+typedef enum {
+       FILTER_UNKOWN = 0,
+       FILTER_BEGIN = 1,
+       FILTER_END = 2
+} filter_packet_state_t;
+
 typedef struct sofia_dispatch_event_s {
        nua_saved_event_t event[1];
        nua_handle_t *nh;
@@ -396,6 +402,9 @@ struct mod_sofia_globals {
        uint32_t max_reg_threads;
        time_t presence_epoch;
        int presence_year;
+       char filter_expression[100];
+       switch_regex_t *filter_re;
+       switch_bool_t filtering;
 };
 extern struct mod_sofia_globals mod_sofia_globals;
 
index 1e28be82a5253d8f83a4111cfccb2fe4ef9e3d78..2757460fbf5e252988e016a029f6ff97ce1beb4e 100644 (file)
@@ -35,6 +35,7 @@
  * Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
  * William King <william.king@quentustech.com>
  * David Knell <david.knell@telng.com>
+ * David Villasmil <david.villasmil@gmail.com>
  *
  * sofia.c -- SOFIA SIP Endpoint (sofia code)
  *
@@ -3450,13 +3451,65 @@ void launch_sofia_profile_thread(sofia_profile_t *profile)
        switch_thread_create(&profile->thread, thd_attr, sofia_profile_thread_run, profile, profile->pool);
 }
 
+static int is_packet_begin_or_end(char *mybuf)
+{
+       if (!strncasecmp( mybuf, "recv ", 3) || !strncasecmp( mybuf, "send ", 3) ) {
+               // Buffer starts with "recv" or "send", this means it's a new packet
+               if (strstr(mybuf, "------------------------------------------------------------------------") != NULL) {
+                       // Buffer also contains the dahsed line, this is good, the complete "header" so to speak
+                       return 1;
+               }
+       } else if (!strcmp(mybuf, "   ------------------------------------------------------------------------\n")) {
+               // Buffer only has the dashed line, this means it is the end of a packet
+               return 2;
+       }
+       return 0;
+}
+
 static void logger(void *logarg, char const *fmt, va_list ap)
 {
-       if (!fmt) return;
+       filter_packet_state_t filter_packet_state;
+    char buf[1024];
+    static switch_stream_handle_t packetstream = { 0 };
+    static switch_bool_t print_this_packet = SWITCH_FALSE;
+    static int ovector[30];
+
+    va_list temp_ap;
+    va_copy(temp_ap,ap);
+
+    if (!fmt) return;
 
-       switch_log_vprintf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, fmt, ap);
+    vsnprintf( buf, 1024, fmt, temp_ap);
+       buf[sizeof(buf)-1] = '\0';
+
+    if (mod_sofia_globals.filtering) {
+       if (switch_regex_perform( buf, mod_sofia_globals.filter_expression, &mod_sofia_globals.filter_re, ovector, sizeof(ovector) / sizeof(ovector[0]) ) > 0) {
+               print_this_packet = SWITCH_TRUE;
+       }
+
+       filter_packet_state = is_packet_begin_or_end(buf);
+
+               if ( filter_packet_state == FILTER_BEGIN ) {
+                       print_this_packet = SWITCH_FALSE;
+                       SWITCH_STANDARD_STREAM(packetstream);
+                       packetstream.write_function(&packetstream, "%s", buf);
+
+       } else if ( filter_packet_state == FILTER_END ) {
+                       if ( print_this_packet == SWITCH_TRUE ) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, "\nFILTER REGEX (%s) FOUND IN: \n <<<%s>>>\n", mod_sofia_globals.filter_expression, (char *)packetstream.data );
+                       }
+                       switch_safe_free(packetstream.data);
+
+       } else {
+                       packetstream.write_function(&packetstream, "%s", buf);
+       }
+    } else {
+       switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, "%s", buf     );
+    }
+       buf[0] = '\0';
 }
 
+
 static su_log_t *sofia_get_logger(const char *name)
 {
        if (!strcasecmp(name, "tport")) {