[FFmpeg-devel] [RFC] libavformat: URL reassembly with IPv6 addresses

Martin Storsjö martin
Fri Feb 26 18:49:48 CET 2010


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, 
+    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