[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