From 21a569f3022e968d74bfde4d1bfff8dab5edd41c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin@martin.st>
Date: Thu, 6 Jan 2011 15:16:50 +0000
Subject: [PATCH] udp: Allow specifying the connect option in
 udp_set_remote_url, too

If the remote address is updated later with this function, the caller
shouldn't set the connect option until in this call.

Originally committed as revision 26245 to svn://svn.ffmpeg.org/ffmpeg/trunk
---
 doc/protocols.texi |  4 ++++
 libavformat/udp.c  | 18 +++++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/doc/protocols.texi b/doc/protocols.texi
index b76e45c3d3f..600f4704582 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -415,9 +415,13 @@ set the time to live value (for multicast only)
 @item connect=@var{1|0}
 Initialize the UDP socket with @code{connect()}. In this case, the
 destination address can't be changed with udp_set_remote_url later.
+If the destination address isn't known at the start, this option can
+be specified in udp_set_remote_url, too.
 This allows finding out the source address for the packets with getsockname,
 and makes writes return with AVERROR(ECONNREFUSED) if "destination
 unreachable" is received.
+For receiving, this gives the benefit of only receiving packets from
+the specified peer address/port.
 @end table
 
 Some usage examples of the udp protocol with @file{ffmpeg} follow.
diff --git a/libavformat/udp.c b/libavformat/udp.c
index b998086407e..0b62c6da2df 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -245,8 +245,9 @@ static int udp_port(struct sockaddr_storage *addr, int addr_len)
 int udp_set_remote_url(URLContext *h, const char *uri)
 {
     UDPContext *s = h->priv_data;
-    char hostname[256];
+    char hostname[256], buf[10];
     int port;
+    const char *p;
 
     av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
 
@@ -256,6 +257,21 @@ int udp_set_remote_url(URLContext *h, const char *uri)
         return AVERROR(EIO);
     }
     s->is_multicast = ff_is_multicast_address((struct sockaddr*) &s->dest_addr);
+    p = strchr(uri, '?');
+    if (p) {
+        if (find_info_tag(buf, sizeof(buf), "connect", p)) {
+            int was_connected = s->is_connected;
+            s->is_connected = strtol(buf, NULL, 10);
+            if (s->is_connected && !was_connected) {
+                if (connect(s->udp_fd, (struct sockaddr *) &s->dest_addr,
+                            s->dest_addr_len)) {
+                    s->is_connected = 0;
+                    av_log(NULL, AV_LOG_ERROR, "connect: %s\n", strerror(errno));
+                    return AVERROR(EIO);
+                }
+            }
+        }
+    }
 
     return 0;
 }
-- 
GitLab