+
+ if (pool_index != -1) {
+ return pool_index;
+ }
+
+ // No match to existing pools.
+ MarkPoolConfig pool;
+ pool.from = from;
+ pool.to = to;
+ config->mark_pools.push_back(pool);
+
+ return config->mark_pools.size() - 1;
+}
+
+bool parse_mark_pool(const string &mark_str, int *from, int *to)
+{
+ size_t split = mark_str.find_first_of('-');
+ if (split == string::npos) {
+ fprintf(stderr, "ERROR: Invalid mark specification '%s' (expected 'X-Y').\n",
+ mark_str.c_str());
+ return false;
+ }
+
+ string from_str(mark_str.begin(), mark_str.begin() + split);
+ string to_str(mark_str.begin() + split + 1, mark_str.end());
+ *from = atoi(from_str.c_str());
+ *to = atoi(to_str.c_str());
+
+ if (*from <= 0 || *from >= 65536 || *to <= 0 || *to >= 65536) {
+ fprintf(stderr, "ERROR: Mark pool range %d-%d is outside legal range [1,65536>.\n",
+ *from, *to);
+ return false;
+ }
+
+ return true;
+}
+
+bool parse_stream(const ConfigLine &line, Config *config)
+{
+ if (line.arguments.size() != 1) {
+ fprintf(stderr, "ERROR: 'stream' takes exactly one argument\n");
+ return false;
+ }
+
+ StreamConfig stream;
+ stream.stream_id = line.arguments[0];
+
+ map<string, string>::const_iterator src_it = line.parameters.find("src");
+ if (src_it == line.parameters.end()) {
+ fprintf(stderr, "WARNING: stream '%s' has no src= attribute, clients will not get any data.\n",
+ stream.stream_id.c_str());
+ } else {
+ stream.src = src_it->second;
+ // TODO: Verify that the URL is parseable?
+ }
+
+ map<string, string>::const_iterator backlog_it = line.parameters.find("backlog_size");
+ if (backlog_it == line.parameters.end()) {
+ stream.backlog_size = DEFAULT_BACKLOG_SIZE;
+ } else {
+ stream.backlog_size = atoi(backlog_it->second.c_str());
+ }
+
+ // Parse marks, if so desired.
+ map<string, string>::const_iterator mark_parm_it = line.parameters.find("mark");
+ if (mark_parm_it == line.parameters.end()) {
+ stream.mark_pool = -1;
+ } else {
+ int from, to;
+ if (!parse_mark_pool(mark_parm_it->second, &from, &to)) {
+ return false;