]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rtsp.c
qdm2: Check data block size for bytes to bits overflow.
[ffmpeg] / libavformat / rtsp.c
index b63f9f68cff7119591e77b4629b317e9e09ee8be..487e910c17688f4f9453e1be68d8c5158600c787 100644 (file)
@@ -81,6 +81,8 @@ const AVOption ff_rtsp_options[] = {
     { "http", "HTTP tunneling", 0, AV_OPT_TYPE_CONST, {(1 << RTSP_LOWER_TRANSPORT_HTTP)}, 0, 0, DEC, "rtsp_transport" },
     RTSP_FLAG_OPTS("rtsp_flags", "RTSP flags"),
     RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"),
+    { "min_port", "Minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC },
+    { "max_port", "Maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC },
     { NULL },
 };
 
@@ -580,8 +582,7 @@ void ff_rtsp_close_streams(AVFormatContext *s)
     }
     av_free(rt->rtsp_streams);
     if (rt->asf_ctx) {
-        av_close_input_stream (rt->asf_ctx);
-        rt->asf_ctx = NULL;
+        avformat_close_input(&rt->asf_ctx);
     }
     av_free(rt->p);
     av_free(rt->recvbuf);
@@ -1104,7 +1105,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
                               int lower_transport, const char *real_challenge)
 {
     RTSPState *rt = s->priv_data;
-    int rtx, j, i, err, interleave = 0;
+    int rtx = 0, j, i, err, interleave = 0, port_off;
     RTSPStream *rtsp_st;
     RTSPMessageHeader reply1, *reply = &reply1;
     char cmd[2048];
@@ -1122,7 +1123,14 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
     /* XXX: we assume the same server is used for the control of each
      * RTSP stream */
 
-    for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
+    /* Choose a random starting offset within the first half of the
+     * port range, to allow for a number of ports to try even if the offset
+     * happens to be at the end of the random range. */
+    port_off = av_get_random_seed() % ((rt->rtp_port_max - rt->rtp_port_min)/2);
+    /* even random offset */
+    port_off -= port_off & 0x01;
+
+    for (j = rt->rtp_port_min + port_off, i = 0; i < rt->nb_rtsp_streams; ++i) {
         char transport[2048];
 
         /*
@@ -1159,16 +1167,14 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
             }
 
             /* first try in specified port range */
-            if (RTSP_RTP_PORT_MIN != 0) {
-                while (j <= RTSP_RTP_PORT_MAX) {
-                    ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
-                                "?localport=%d", j);
-                    /* we will use two ports per rtp stream (rtp and rtcp) */
-                    j += 2;
-                    if (ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE,
-                                   &s->interrupt_callback, NULL) == 0)
-                        goto rtp_opened;
-                }
+            while (j <= rt->rtp_port_max) {
+                ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
+                            "?localport=%d", j);
+                /* we will use two ports per rtp stream (rtp and rtcp) */
+                j += 2;
+                if (!ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE,
+                               &s->interrupt_callback, NULL))
+                    goto rtp_opened;
             }
 
             av_log(s, AV_LOG_ERROR, "Unable to open an input RTP port\n");
@@ -1359,6 +1365,13 @@ int ff_rtsp_connect(AVFormatContext *s)
     struct sockaddr_storage peer;
     socklen_t peer_len = sizeof(peer);
 
+    if (rt->rtp_port_max < rt->rtp_port_min) {
+        av_log(s, AV_LOG_ERROR, "Invalid UDP port range, max port %d less "
+                                "than min port %d\n", rt->rtp_port_max,
+                                                      rt->rtp_port_min);
+        return AVERROR(EINVAL);
+    }
+
     if (!ff_network_init())
         return AVERROR(EIO);