Dale Ghent
2004-Aug-06 14:57 UTC
[icecast-dev] [PATCH] Add per-listener and per-mount connection time limits.
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@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;