diff --git a/src/cfgfile.c b/src/cfgfile.c index bd286448..b6f036b7 100644 --- a/src/cfgfile.c +++ b/src/cfgfile.c @@ -1737,6 +1737,14 @@ static void _parse_mount(xmlDocPtr doc, } else if (xmlStrcmp(node->name, XMLSTR("dump-file")) == 0) { mount->dumpfile = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + } else if (xmlStrcmp(node->name, XMLSTR("dump-file-size-limit")) == 0) { + unsigned int val = mount->dumpfile_size_limit; + __read_unsigned_int(configuration, doc, node, &val, 0, UINT_MAX); + mount->dumpfile_size_limit = val; + } else if (xmlStrcmp(node->name, XMLSTR("dump-file-time-limit")) == 0) { + unsigned int val = mount->dumpfile_time_limit; + __read_unsigned_int(configuration, doc, node, &val, 0, UINT_MAX); + mount->dumpfile_time_limit = val; } else if (xmlStrcmp(node->name, XMLSTR("intro")) == 0) { mount->intro_filename = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); @@ -2989,6 +2997,10 @@ static void merge_mounts(mount_proxy * dst, mount_proxy * src) if (!dst->dumpfile) dst->dumpfile = (char*)xmlStrdup((xmlChar*)src->dumpfile); + if (!dst->dumpfile_size_limit) + dst->dumpfile_size_limit = src->dumpfile_size_limit; + if (!dst->dumpfile_time_limit) + dst->dumpfile_time_limit = src->dumpfile_time_limit; if (!dst->intro_filename) dst->intro_filename = (char*)xmlStrdup((xmlChar*)src->intro_filename); if (!dst->fallback_when_full) diff --git a/src/cfgfile.h b/src/cfgfile.h index 988d5a41..7539843e 100644 --- a/src/cfgfile.h +++ b/src/cfgfile.h @@ -88,6 +88,8 @@ typedef struct _mount_proxy { * NULL to not dump. */ char *dumpfile; + uint64_t dumpfile_size_limit; + unsigned int dumpfile_time_limit; /* Send contents of file to client before the stream */ char *intro_filename; /* Switch new listener to fallback source when max listeners reached */ diff --git a/src/source.c b/src/source.c index 5fcf7375..2926723b 100644 --- a/src/source.c +++ b/src/source.c @@ -1183,13 +1183,27 @@ static void source_apply_mount (ice_config_t *config, source_t *source, mount_pr source->fallback_mount = NULL; } + /* Dumpfile settings */ if (mountinfo && mountinfo->dumpfile) { util_replace_string(&(source->dumpfilename), mountinfo->dumpfile); } else { free(source->dumpfilename); source->dumpfilename = NULL; + if (source->dumpfile) { + ICECAST_LOG_INFO("Stopping dumpfile as it is now de-configured for source %p at mountpoint %#H.", source, source->mount); + source_kill_dumpfile(source); + } } + if (mountinfo) { + source->dumpfile_size_limit = mountinfo->dumpfile_size_limit; + source->dumpfile_time_limit = mountinfo->dumpfile_time_limit; + } else { + source->dumpfile_size_limit = 0; + source->dumpfile_time_limit = 0; + } + + if (source->intro_file) { fclose (source->intro_file); @@ -1483,6 +1497,17 @@ bool source_write_dumpfile(source_t *source, const void *buffer, size_t len) source->dumpfile_written += len; + if (source->dumpfile_size_limit && source->dumpfile_written > source->dumpfile_size_limit) { + ICECAST_LOG_INFO("Dumpfile for source %p at mountpoint %#H reached size limit. Dumpfile will be disabled.", source, source->mount); + source_kill_dumpfile(source); + } else if (source->dumpfile_time_limit) { + time_t now = time(NULL); + if (now > (source->dumpfile_start + source->dumpfile_time_limit)) { + ICECAST_LOG_INFO("Dumpfile for source %p at mountpoint %#H reached time limit. Dumpfile will be disabled.", source, source->mount); + source_kill_dumpfile(source); + } + } + return true; } diff --git a/src/source.h b/src/source.h index 52f172d9..a9b6c042 100644 --- a/src/source.h +++ b/src/source.h @@ -57,6 +57,8 @@ struct source_tag { /* Dumpfile related data */ /* Config */ char *dumpfilename; /* Name of a file to dump incoming stream to */ + uint64_t dumpfile_size_limit; + unsigned int dumpfile_time_limit; /* Runtime */ FILE *dumpfile; time_t dumpfile_start;