[icecast-dev] [PATCH] Add per-listener and per-mount connection time limits.

Dale Ghent daleg at elemental.org
Fri Mar 5 10:40:12 PST 2004


Attached you will find a patch against the icecast-2.0.0 released source
code which implements listener time limits on a global or mount-specific
scope.

Two new configuration elements are added with this patch:

client-time-limit: This is a GLOBAL directive which covers all
connections. Its value is given in seconds. So for example, if you want to
limit all listeners on all mount points to 1 hour, it will look like this:

      <client-time-limit>3600</client-time-limit>

max-listener-time: This is a MOUNT-SPECIFIC directive - it can only be
given inside a <mount></mount> container. It also takes a value of
seconds. This directive enables you to set a listener time limit on a
specific mount point. These rules are observed:

            * IF client-time-limit and max-listener-time are present and
are set to a value > 0, max-listener-time's value overrides the value set
in client-time-limit. This is so you can, for example, Limit all clients
to 30 minutes, but have clients on a specific mount point be limited to 20
minutes or 2 hours, for example.

            * IF only max-listener-time is set, only listeners connected
to its associatated mount are effected by the time limit.

            * IF only client-time-limit is set, ALL listeners connected to
the icecast server, no matter the mount point, are effected.

            * Default behaviour is NO limit.

To apply this patch, put it in your icecasr-2.0.0 source tree root, and
execute 'patch -p0 < timelimiter.patch'

Please give me feed back if this is working as you expect.

//dale
-------------- next part --------------
*** src/cfgfile.c.orig	Fri Dec 12 10:23:08 2003
--- src/cfgfile.c	Fri Mar  5 13:12:03 2004
***************
*** 19,24 ****
--- 19,25 ----
  #define CONFIG_DEFAULT_ADMIN "icemaster at localhost"
  #define CONFIG_DEFAULT_CLIENT_LIMIT 256
  #define CONFIG_DEFAULT_SOURCE_LIMIT 16
+ #define CONFIG_DEFAULT_CLIENT_TIME_LIMIT 0
  #define CONFIG_DEFAULT_QUEUE_SIZE_LIMIT (100*1024)
  #define CONFIG_DEFAULT_THREADPOOL_SIZE 4
  #define CONFIG_DEFAULT_CLIENT_TIMEOUT 30
***************
*** 276,281 ****
--- 277,283 ----
      configuration->admin = CONFIG_DEFAULT_ADMIN;
      configuration->client_limit = CONFIG_DEFAULT_CLIENT_LIMIT;
      configuration->source_limit = CONFIG_DEFAULT_SOURCE_LIMIT;
+     configuration->client_time_limit = CONFIG_DEFAULT_CLIENT_TIME_LIMIT;
      configuration->queue_size_limit = CONFIG_DEFAULT_QUEUE_SIZE_LIMIT;
      configuration->threadpool_size = CONFIG_DEFAULT_THREADPOOL_SIZE;
      configuration->client_timeout = CONFIG_DEFAULT_CLIENT_TIMEOUT;
***************
*** 409,414 ****
--- 411,420 ----
              tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
              configuration->source_limit = atoi(tmp);
              if (tmp) xmlFree(tmp);
+         } else if (strcmp(node->name, "client-time-limit") == 0) {
+             tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+             configuration->client_time_limit = atoi(tmp);
+             if (tmp) xmlFree(tmp);
          } else if (strcmp(node->name, "queue-size") == 0) {
              tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
              configuration->queue_size_limit = atoi(tmp);
***************
*** 452,457 ****
--- 458,464 ----
          configuration->mounts = mount;
  
      mount->max_listeners = -1;
+     mount->max_listener_time = 0;
      mount->next = NULL;
  
      do {
***************
*** 481,486 ****
--- 488,498 ----
          else if (strcmp(node->name, "max-listeners") == 0) {
              tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
              mount->max_listeners = atoi(tmp);
+             if(tmp) xmlFree(tmp);
+         }
+         else if (strcmp(node->name, "max-listener-time") == 0) {
+             tmp =  (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+             mount->max_listener_time = atoi(tmp);
              if(tmp) xmlFree(tmp);
          }
      } while ((node = node->next));
*** src/cfgfile.h.orig	Fri Dec 12 09:39:53 2003
--- src/cfgfile.h	Fri Mar  5 13:12:16 2004
***************
*** 39,44 ****
--- 39,47 ----
                         to not dump. */
      int max_listeners; /* Max listeners for this mountpoint only. -1 to not 
                            limit here (i.e. only use the global limit) */
+     int max_listener_time; /* Maximum amount of time in seconds a listener can
+                               be connected to this mount. -1 to not limit here
+                               (i.e. only use the global limit) */
      char *fallback_mount;
      struct _mount_proxy *next;
  } mount_proxy;
***************
*** 65,70 ****
--- 68,74 ----
  
      int client_limit;
      int source_limit;
+     long client_time_limit;
      long queue_size_limit;
      int threadpool_size;
      int client_timeout;
*** src/source.c.orig	Mon Dec 29 10:38:58 2003
--- src/source.c	Fri Mar  5 13:11:30 2004
***************
*** 65,70 ****
--- 65,71 ----
      src->num_yp_directories = 0;
      src->listeners = 0;
      src->max_listeners = -1;
+     src->max_listener_time = 0;
      src->send_return = 0;
      src->dumpfilename = NULL;
      src->dumpfile = NULL;
***************
*** 77,82 ****
--- 78,85 ----
          src->max_listeners = mountinfo->max_listeners;
          if (mountinfo->dumpfile != NULL)
              src->dumpfilename = strdup (mountinfo->dumpfile);
+         if (mountinfo->max_listener_time != NULL)
+             src->max_listener_time = mountinfo->max_listener_time;
      }
  
      if(src->dumpfilename != NULL) {
***************
*** 191,196 ****
--- 194,200 ----
  
      refbuf_t *refbuf, *abuf;
      int data_done;
+     int client_connect_time;
  
      int listeners = 0;
  #ifdef USE_YP
***************
*** 202,207 ****
--- 206,214 ----
  #endif
  
      long queue_limit;
+     int global_listener_time_limit;
+     int mount_listener_time_limit;
+     int listener_time_limit;
      ice_config_t *config;
      char *hostname;
      int port;
***************
*** 209,214 ****
--- 216,223 ----
      config = config_get_config();
      
      queue_limit = config->queue_size_limit;
+     global_listener_time_limit = config->client_time_limit;
+     mount_listener_time_limit = source->max_listener_time;
      timeout = config->source_timeout;
      hostname = config->hostname;
      port = config->port;
***************
*** 428,435 ****
              avl_node_wlock(client_node);
  
              client = (client_t *)client_node->key;
!             
              data_done = 0;
  
              /* do we have any old buffers? */
              abuf = refbuf_queue_remove(&client->queue);
--- 437,468 ----
              avl_node_wlock(client_node);
  
              client = (client_t *)client_node->key;
! 
              data_done = 0;
+             listener_time_limit = 0;
+ 
+             /* Kick any clients that have overstayed their time limit. */
+             if ((global_listener_time_limit > 0) ||
+                (mount_listener_time_limit > 0)) {
+                 current_time = time(NULL);
+                 client_connect_time = current_time - client->con->con_time;
+ 
+                 if ((global_listener_time_limit > 0) &&
+                    (mount_listener_time_limit > 0)) {
+                     listener_time_limit = mount_listener_time_limit;
+                 } else if (global_listener_time_limit > 0) {
+                     listener_time_limit = global_listener_time_limit;
+                 } else if (mount_listener_time_limit > 0) {
+                     listener_time_limit = mount_listener_time_limit;
+                 }
+  
+                 if (client_connect_time > listener_time_limit) {
+                     DEBUG0("Client exceeded configured listener time limit");
+                     client->con->error = 1;
+                     data_done = 1;
+                     break;
+                 }
+             }
  
              /* do we have any old buffers? */
              abuf = refbuf_queue_remove(&client->queue);
*** src/source.h.orig	Sun Jul 20 21:58:54 2003
--- src/source.h	Fri Mar  5 13:12:09 2004
***************
*** 38,43 ****
--- 38,44 ----
      int    num_yp_directories;
      long listeners;
      long max_listeners;
+     int max_listener_time;
      int yp_public;
      int send_return;
  } source_t;


More information about the Icecast-dev mailing list