]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-8377 Adding expanded support for limit_* functionality for mod_hiredis
authorWilliam King <william.king@quentustech.com>
Wed, 21 Oct 2015 21:55:28 +0000 (14:55 -0700)
committerWilliam King <william.king@quentustech.com>
Wed, 21 Oct 2015 21:56:21 +0000 (14:56 -0700)
src/mod/applications/mod_hiredis/mod_hiredis.c
src/mod/applications/mod_hiredis/mod_hiredis.h

index 8a6077390cdc6feafcdf8a04e401a0bee23a43a7..2b1b85459f9a45de350a97e29e1787efed707ea4 100644 (file)
@@ -41,7 +41,7 @@ SWITCH_STANDARD_APP(raw_app)
        switch_channel_t *channel = switch_core_session_get_channel(session);
        char *response = NULL, *profile_name = NULL, *cmd = NULL;
        hiredis_profile_t *profile = NULL;
-       
+
        if ( !zstr(data) ) {
                profile_name = strdup(data);
        } else {
@@ -63,7 +63,7 @@ SWITCH_STANDARD_APP(raw_app)
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: Unable to locate profile[%s]\n", profile_name);
                return;
        }
-       
+
        if ( hiredis_profile_execute_sync(profile, cmd, &response) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", profile_name, cmd, response);
        }
@@ -81,13 +81,13 @@ SWITCH_STANDARD_API(raw_api)
        hiredis_profile_t *profile = NULL;
        char *data = NULL, *input = NULL, *response = NULL;
        switch_status_t status = SWITCH_STATUS_SUCCESS;
-       
+
        if ( !zstr(cmd) ) {
                input = strdup(cmd);
        } else {
                switch_goto_status(SWITCH_STATUS_GENERR, done);
        }
-       
+
        if ( (data = strchr(input, ' '))) {
                *data = '\0';
                data++;
@@ -101,7 +101,7 @@ SWITCH_STANDARD_API(raw_api)
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: Unable to locate profile[%s]\n", input);
                switch_goto_status(SWITCH_STATUS_GENERR, done);
        }
-       
+
        if ( hiredis_profile_execute_sync(profile, data, &response) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] reason:[%s]\n", input, data, response);
                switch_goto_status(SWITCH_STATUS_GENERR, done);
@@ -114,24 +114,26 @@ SWITCH_STANDARD_API(raw_api)
        return status;
 }
 
-/* 
-SWITCH_LIMIT_INCR(name) static switch_status_t name (switch_core_session_t *session, const char *realm, const char *resource, 
+/*
+SWITCH_LIMIT_INCR(name) static switch_status_t name (switch_core_session_t *session, const char *realm, const char *resource,
                                                      const int max, const int interval)
 */
 SWITCH_LIMIT_INCR(hiredis_limit_incr)
 {
        switch_channel_t *channel = switch_core_session_get_channel(session);
        hiredis_profile_t *profile = NULL;
-       char *hashkey = NULL, *response = NULL;
+       char *hashkey = NULL, *response = NULL, *limit_key = NULL;
        int64_t count = 0; /* Redis defines the incr action as to be performed on a 64 bit signed integer */
        time_t now = switch_epoch_time_now(NULL);
        switch_status_t status = SWITCH_STATUS_SUCCESS;
+       hiredis_limit_pvt_t *limit_pvt = NULL;
+       switch_memory_pool_t *session_pool = switch_core_session_get_pool(session);
 
        if ( zstr(realm) ) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: realm must be defined\n");
                switch_goto_status(SWITCH_STATUS_GENERR, done);
        }
-       
+
        profile = switch_core_hash_find(mod_hiredis_globals.profiles, realm);
 
        if ( !profile ) {
@@ -140,11 +142,13 @@ SWITCH_LIMIT_INCR(hiredis_limit_incr)
        }
 
        if ( interval ) {
-               hashkey = switch_mprintf("incr %s_%d", resource, now % interval);
+               limit_key = switch_mprintf("%s_%d", resource, now % interval);
        } else {
-               hashkey = switch_mprintf("incr %s", resource);
+               limit_key = switch_mprintf("%s", resource);
        }
 
+       hashkey = switch_mprintf("incr %s", limit_key);
+
        if ( hiredis_profile_execute_sync(profile, hashkey, &response) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", realm, hashkey, response);
                switch_channel_set_variable(channel, "hiredis_raw_response", response);
@@ -153,6 +157,14 @@ SWITCH_LIMIT_INCR(hiredis_limit_incr)
 
        switch_channel_set_variable(channel, "hiredis_raw_response", response);
 
+       limit_pvt = switch_core_alloc(session_pool, sizeof(hiredis_limit_pvt_t));
+       limit_pvt->next = switch_channel_get_private(channel, "hiredis_limit_pvt");
+       limit_pvt->realm = switch_core_strdup(session_pool, realm);
+       limit_pvt->resource = switch_core_strdup(session_pool, resource);
+       limit_pvt->limit_key = switch_core_strdup(session_pool, limit_key);
+       limit_pvt->inc = 1;
+       switch_channel_set_private(channel, "hiredis_limit_pvt", limit_pvt);
+
        count = atoll(response);
 
        if ( !count || count > max ) {
@@ -160,6 +172,7 @@ SWITCH_LIMIT_INCR(hiredis_limit_incr)
        }
 
  done:
+       switch_safe_free(limit_key);
        switch_safe_free(response);
        switch_safe_free(hashkey);
        return status;
@@ -174,32 +187,48 @@ SWITCH_LIMIT_RELEASE(hiredis_limit_release)
        hiredis_profile_t *profile = switch_core_hash_find(mod_hiredis_globals.profiles, realm);
        char *hashkey = NULL, *response = NULL;
        switch_status_t status = SWITCH_STATUS_SUCCESS;
+       hiredis_limit_pvt_t *limit_pvt = switch_channel_get_private(channel, "hiredis_limit_pvt");
 
        if ( !zstr(realm) ) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: realm must be defined\n");
                switch_goto_status(SWITCH_STATUS_GENERR, done);
        }
-       
+
        if ( !profile ) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: Unable to locate profile[%s]\n", realm);
                switch_goto_status(SWITCH_STATUS_GENERR, done);
        }
 
+       /* If realm and resource are NULL, then clear all of the limits */
        if ( !realm && !resource ) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis does not yet support release on NULL realm[%s] and resource[%s]\n", realm, resource);
-               switch_goto_status(SWITCH_STATUS_GENERR, done);
-       }
+               hiredis_limit_pvt_t *tmp = limit_pvt;
 
-       hashkey = switch_mprintf("decr %s", resource);
+               while (tmp) {
+                       hashkey = switch_mprintf("decr %s", tmp->limit_key);
+                       limit_pvt = tmp->next;
+
+                       if ( hiredis_profile_execute_sync(profile, hashkey, &response) != SWITCH_STATUS_SUCCESS) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n",
+                                                                 tmp->realm, hashkey, response);
+                       }
+
+                       tmp = limit_pvt;
+                       switch_safe_free(response);
+                       switch_safe_free(hashkey);
+               }
+       } else {
+
+               hashkey = switch_mprintf("decr %s", limit_pvt->limit_key);
+
+               if ( hiredis_profile_execute_sync(profile, hashkey, &response) != SWITCH_STATUS_SUCCESS) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", realm, hashkey, response);
+                       switch_channel_set_variable(channel, "hiredis_raw_response", response);
+                       switch_goto_status(SWITCH_STATUS_GENERR, done);
+               }
 
-       if ( hiredis_profile_execute_sync(profile, hashkey, &response) != SWITCH_STATUS_SUCCESS) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", realm, hashkey, response);
                switch_channel_set_variable(channel, "hiredis_raw_response", response);
-               switch_goto_status(SWITCH_STATUS_GENERR, done);
        }
 
-       switch_channel_set_variable(channel, "hiredis_raw_response", response);
-
  done:
        switch_safe_free(response);
        switch_safe_free(hashkey);
@@ -212,14 +241,14 @@ SWITCH_LIMIT_USAGE(name) static int name (const char *realm, const char *resourc
 SWITCH_LIMIT_USAGE(hiredis_limit_usage)
 {
        hiredis_profile_t *profile = switch_core_hash_find(mod_hiredis_globals.profiles, realm);
-       int64_t count = 0; /* Redis defines the incr action as to be performed on a 64 bit signed integer */    
+       int64_t count = 0; /* Redis defines the incr action as to be performed on a 64 bit signed integer */
        char *hashkey = NULL, *response = NULL;
-       
+
        if ( !zstr(realm) ) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: realm must be defined\n");
                goto err;
        }
-       
+
        if ( !profile ) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: Unable to locate profile[%s]\n", realm);
                goto err;
@@ -237,7 +266,7 @@ SWITCH_LIMIT_USAGE(hiredis_limit_usage)
        switch_safe_free(response);
        switch_safe_free(hashkey);
        return count;
-       
+
  err:
        switch_safe_free(response);
        switch_safe_free(hashkey);
@@ -251,7 +280,7 @@ SWITCH_LIMIT_RESET(hiredis_limit_reset)
 {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
                                          "hiredis: unable to globally reset hiredis limit resources. Use 'hiredis_raw set resource_name 0'\n");
-               
+
        return SWITCH_STATUS_GENERR;
 }
 
@@ -263,12 +292,12 @@ SWITCH_LIMIT_INTERVAL_RESET(hiredis_limit_interval_reset)
        hiredis_profile_t *profile = switch_core_hash_find(mod_hiredis_globals.profiles, realm);
        switch_status_t status = SWITCH_STATUS_SUCCESS;
        char *hashkey = NULL, *response = NULL;
-       
+
        if ( !zstr(realm) ) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: realm must be defined\n");
                switch_goto_status(SWITCH_STATUS_GENERR, done);
        }
-       
+
        if ( !profile ) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: Unable to locate profile[%s]\n", realm);
                switch_goto_status(SWITCH_STATUS_GENERR, done);
@@ -306,7 +335,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_hiredis_load)
        mod_hiredis_globals.pool = pool;
 
        switch_core_hash_init(&(mod_hiredis_globals.profiles));
-       
+
        if ( mod_hiredis_do_config() != SWITCH_STATUS_SUCCESS ) {
                return SWITCH_STATUS_GENERR;
        }
index becb565dcc0ce528e4ff6071fdf47ac67c3c6111..5655fc75018b3e11088ee5320ea5da1d4e8fb4a3 100644 (file)
@@ -29,9 +29,17 @@ typedef struct hiredis_profile_s {
   int debug;
 
   hiredis_connection_t *conn;
-  hiredis_connection_t *conn_head;  
+  hiredis_connection_t *conn_head;
 } hiredis_profile_t;
 
+typedef struct hiredis_limit_pvt_s {
+  char *realm;
+  char *resource;
+  char *limit_key;
+  int inc;
+  struct hiredis_limit_pvt_s *next;
+} hiredis_limit_pvt_t;
+
 switch_status_t mod_hiredis_do_config();
 switch_status_t hiredis_profile_create(hiredis_profile_t **new_profile, char *name, uint8_t port);
 switch_status_t hiredis_profile_destroy(hiredis_profile_t **old_profile);