diff --git a/conf/icecast.xml.in b/conf/icecast.xml.in index 1d349127..63fd5b05 100644 --- a/conf/icecast.xml.in +++ b/conf/icecast.xml.in @@ -87,10 +87,10 @@ the details passed are based on and --> - + - diff --git a/src/flv.c b/src/flv.c index 915e246a..04c954b7 100644 --- a/src/flv.c +++ b/src/flv.c @@ -245,7 +245,7 @@ int flv_write_metadata (struct flv *flv, struct metadata_block *meta, const char { char *value = stats_get_value (mount, "server_name"); - flvmeta = flv_meta_allocate (200); + flvmeta = flv_meta_allocate (470); if (value) flv_meta_append_string (flvmeta, "name", value); free (value); @@ -277,7 +277,7 @@ int flv_write_metadata (struct flv *flv, struct metadata_block *meta, const char flv_meta_append_bool (flvmeta, "hasMetadata", 1); flv_meta_append_bool (flvmeta, "hasVideo", 0); flv_meta_append_bool (flvmeta, "hasAudio", 1); - flv_meta_append_string (flvmeta, NULL, NULL); + flv_meta_append_end_marker (flvmeta); flvm = (struct flvmeta *)flvmeta->data; meta_copied = flvm->meta_pos - sizeof (*flvm); if (meta_copied + 15 + flv->wrapper_offset > wrapper->len) @@ -437,35 +437,62 @@ refbuf_t *flv_meta_allocate (size_t len) } +void flv_meta_append_end_marker (refbuf_t *buffer) +{ + struct flvmeta *flvm = (struct flvmeta *)buffer->data; + unsigned char *ptr = (unsigned char *)buffer->data + flvm->meta_pos; + + if (3 + flvm->meta_pos > buffer->len) { + WARN0 ("not enough space for end-of-metadata marker"); + return; + } + + memcpy (ptr, "\000\000\011", 3); + flvm->meta_pos += 3; +} + + static int flv_meta_increase (refbuf_t *buffer, int taglen, int valuelen) { struct flvmeta *flvm = (struct flvmeta *)buffer->data; - unsigned char *array_size_loc = (unsigned char *)buffer->data + sizeof (*flvm) + 16; - if (taglen + valuelen + 3 + flvm->meta_pos > buffer->len - 3) - taglen = 0; // force end of the metadata - if (taglen == 0) + // meta tag increases based on 2 byte size, tag, 1 byte type, value + // valuelen should include a size field for string + unsigned int meta_len = 2 + taglen + 1 + valuelen; + // allow 3 extra on target as there needs to be an end tag + unsigned int target_len = flvm->meta_pos + meta_len + 3; + + while (target_len > buffer->len) { - DEBUG1 ("%d array elements", flvm->arraylen); - memcpy (buffer->data+flvm->meta_pos, "\000\000\011", 3); - flvm->meta_pos += 3; - return -1; + if (target_len > 16000) return -1; // avoid going nuts + unsigned new_len = (((target_len >> 12) + 1) << 12); // use 4k blocks + void *p = realloc (buffer->data, new_len); + if (p == NULL) return -1; + buffer->data = p; + buffer->len = new_len; + flvm = (struct flvmeta *)p; } + flvm->arraylen++; + unsigned char *array_size_loc = (unsigned char *)buffer->data + sizeof (*flvm) + 16; flv_write_UI16 (array_size_loc, flvm->arraylen); // over 64k tags not handled - flvm->meta_pos += (2 + taglen + 1 + valuelen); - return 0; + int pos = flvm->meta_pos; + flvm->meta_pos += meta_len; + return pos; } void flv_meta_append_bool (refbuf_t *buffer, const char *tag, int value) { int taglen = tag ? strlen (tag) : 0; - struct flvmeta *flvm = (struct flvmeta *)buffer->data; - unsigned char *ptr = (unsigned char *)buffer->data + flvm->meta_pos; - if (flv_meta_increase (buffer, taglen, 1) < 0) + int pos = flv_meta_increase (buffer, taglen, 1); + if (pos < 0) + { + WARN1 ("not enough space for %s", tag); return; + } + unsigned char *ptr = (unsigned char *)buffer->data + pos; flv_write_UI16 (ptr, taglen); memcpy (ptr+2, tag, taglen); @@ -478,12 +505,15 @@ void flv_meta_append_bool (refbuf_t *buffer, const char *tag, int value) void flv_meta_append_number (refbuf_t *buffer, const char *tag, double value) { int taglen = 0; - struct flvmeta *flvm = (struct flvmeta *)buffer->data; - unsigned char *ptr = (unsigned char *)buffer->data + flvm->meta_pos; if (tag) taglen = strlen (tag); - if (flv_meta_increase (buffer, taglen, 8) < 0) + int pos = flv_meta_increase (buffer, taglen, 8); + if (pos < 0) + { + WARN1 ("not enough space for %s", tag); return; + } + unsigned char *ptr = (unsigned char *)buffer->data + pos; flv_write_UI16 (ptr, taglen); memcpy (ptr+2, tag, taglen); @@ -498,14 +528,18 @@ void flv_meta_append_number (refbuf_t *buffer, const char *tag, double value) void flv_meta_append_string (refbuf_t *buffer, const char *tag, const char *value) { int taglen = 0, valuelen = 0; - struct flvmeta *flvm = (struct flvmeta *)buffer->data; - unsigned char *ptr = (unsigned char *)buffer->data + flvm->meta_pos; if (tag) taglen = strlen (tag); if (value) valuelen = strlen (value); - if (flv_meta_increase (buffer, taglen, valuelen+2) < 0) + // account for extra 2 bytes for length field + int pos = flv_meta_increase (buffer, taglen, valuelen+2); + if (pos < 0) + { + WARN1 ("not enough space for %s", tag); return; + } + unsigned char *ptr = (unsigned char *)buffer->data + pos; flv_write_UI16 (ptr, taglen); memcpy (ptr+2, tag, taglen); diff --git a/src/flv.h b/src/flv.h index c14c7b89..d17f7650 100644 --- a/src/flv.h +++ b/src/flv.h @@ -47,3 +47,4 @@ refbuf_t *flv_meta_allocate (size_t len); void flv_meta_append_string (refbuf_t *buffer, const char *tag, const char *value); void flv_meta_append_number (refbuf_t *buffer, const char *tag, double value); void flv_meta_append_bool (refbuf_t *buffer, const char *tag, int value); +void flv_meta_append_end_marker (refbuf_t *buffer); diff --git a/src/format_mp3.c b/src/format_mp3.c index 4100a7b9..4e669f20 100644 --- a/src/format_mp3.c +++ b/src/format_mp3.c @@ -455,7 +455,7 @@ static void metadata_setup (source_t *source) refbuf_t *icy = refbuf_new (size); if (icy) { - refbuf_t *flvmeta = flv_meta_allocate (4000); + refbuf_t *flvmeta = flv_meta_allocate (400); refbuf_t *iceblock = refbuf_new (4096); icy_client_in *icy_in = source->client->format_data; mpeg_sync *mpeg_sync = &icy_in->sync; @@ -539,7 +539,7 @@ static void metadata_setup (source_t *source) INFO3 ("icy metadata on %s as (%d) %.80s...", source->mount, icy->data[0], icy->data+1); yp_touch (source->mount, source->stats); - flv_meta_append_string (flvmeta, NULL, NULL); + flv_meta_append_end_marker (flvmeta); if (ib_len > 0) ib_len--; // add nul char to help parsing iceblock->len -= ib_len;