[FFmpeg-devel] [RFC] libavformat: URL reassembly with IPv6 addresses
Martin Storsjö
martin
Fri Feb 26 18:49:48 CET 2010
Hi,
Currently, libavformat is a bit lacking when it comes to handling URLs
with numerical IPv6 addresses. Doing ffmpeg -i
http://[1234:5678:90ab::1]/foo doesn't work, for instance.
Since IPv6 addresses use : as delimiters, they can't be written directly
as such into urls instead of a host name, but the address must be enclosed
in [], according to RFC 2732.
url_split handles this correctly, but the cases where URLs are reassembled
from individual components aren't prepared for this.
I can think of three different ways of solving this, none of them totally
optimal for every case.
1) If the url isn't going to be visible outside of libavformat (e.g. when
opening an internal TCP URLContext within the HTTP protocol), always add
[] around the hostname. This breaks strict compliance with RFCs, but works
just fine as long as the URL will be parsed by url_split internally later.
In http.c, this could look like this:
- snprintf(buf, sizeof(buf), "tcp://%s:%d", hostname, port);
+ snprintf(buf, sizeof(buf), "tcp://[%s]:%d", hostname, port);
2) If assembling a (long) URL with a single snprintf call, add macros to
help adding the brackets if necessary. The macros could look like this:
#define URL_HOST_PRE(x) (strchr(x, ':') ? "[" : "")
#define URL_HOST_POST(x) (strchr(x, ':') ? "]" : "")
And potential usage in rtmpproto.c:
- snprintf(tcurl, sizeof(tcurl), "%s://%s:%d/%s", proto, host, port,
rt->app);
+ snprintf(tcurl, sizeof(tcurl), "%s://%s%s%s:%d/%s", proto,
URL_HOST_PRE(host), host, URL_HOST_POST(host), port, rt->app);
This still makes the line a bit unwieldy, though.
3) Add a separate function for appending a properly escaped hostname to a
URL. This feels the cleanest to me, but requires a bit more changes to all
the current occurrances of snprintf assembly of URLs, splitting out the
"append the hostname" part from each case. The function could look
something like this:
void url_host_cat(char *str, int size, const char *hostname)
{
if (strchr(hostname, ':')) {
av_strlcat(str, "[", size);
av_strlcat(str, hostname, size);
av_strlcat(str, "]", size);
} else {
av_strlcat(str, hostname, size);
}
}
Opinions on this matter?
// Martin
More information about the ffmpeg-devel
mailing list