diff mbox

[FFmpeg-devel] avformat/rtsp: support rtsps

Message ID 1476635077-47726-1-git-send-email-jayridge@gmail.com
State Changes Requested
Headers show

Commit Message

Jay Oct. 16, 2016, 4:24 p.m. UTC
From: Jay Ridgeway <jayridge@gmail.com>

Pass TLS args to support RTSPS. This patch requires TLS patch.
---
 libavformat/rtsp.c | 19 ++++++++++++++++---
 libavformat/rtsp.h |  8 ++++++++
 2 files changed, 24 insertions(+), 3 deletions(-)

Comments

wm4 Oct. 16, 2016, 5:22 p.m. UTC | #1
On Sun, 16 Oct 2016 12:24:37 -0400
jayridge@gmail.com wrote:

> From: Jay Ridgeway <jayridge@gmail.com>
> 
> Pass TLS args to support RTSPS. This patch requires TLS patch.
> ---
>  libavformat/rtsp.c | 19 ++++++++++++++++---
>  libavformat/rtsp.h |  8 ++++++++
>  2 files changed, 24 insertions(+), 3 deletions(-)
> 
> diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
> index c6292c5..53ecb6c 100644
> --- a/libavformat/rtsp.c
> +++ b/libavformat/rtsp.c
> @@ -78,6 +78,7 @@
>      { "reorder_queue_size", "set number of packets to buffer for handling of reordered packets", OFFSET(reordering_queue_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC }, \
>      { "buffer_size",        "Underlying protocol send/receive buffer size",                  OFFSET(buffer_size),           AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC|ENC } \
>  
> +#define NONNULLSTR(s) (s ? s : "")
>  
>  const AVOption ff_rtsp_options[] = {
>      { "initial_pause",  "do not start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
> @@ -97,6 +98,10 @@ const AVOption ff_rtsp_options[] = {
>      { "stimeout", "set timeout (in microseconds) of socket TCP I/O operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC },
>      COMMON_OPTS(),
>      { "user-agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC },
> +    { "ca_file", "Certificate Authority database file", OFFSET(ca_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC|ENC },
> +    { "tls_verify", "verify the peer certificate", OFFSET(verify), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC|ENC},
> +    { "cert_file", "certificate file", OFFSET(cert_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC|ENC },
> +    { "key_file", "private key file", OFFSET(key_file),  AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC|ENC },
>      { NULL },
>  };
>  
> @@ -1812,9 +1817,17 @@ redirect:
>      } else {
>          int ret;
>          /* open the tcp connection */
> -        ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL,
> -                    host, port,
> -                    "?timeout=%d", rt->stimeout);
> +        if (strcmp("tls", lower_rtsp_proto) == 0) {
> +            ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL,
> +                        host, port,
> +                        "?timeout=%d&verify=%d&cafile=%s&cert_file=%s&key_file=%s",
> +                        rt->stimeout, rt->verify, NONNULLSTR(rt->ca_file),
> +                        NONNULLSTR(rt->cert_file), NONNULLSTR(rt->key_file));
> +        } else {
> +            ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL,
> +                        host, port,
> +                        "?timeout=%d", rt->stimeout);
> +        }
>          if ((ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
>                         &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL)) < 0) {
>              err = ret;
> diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
> index 852fd67..fa872a8 100644
> --- a/libavformat/rtsp.h
> +++ b/libavformat/rtsp.h
> @@ -408,6 +408,14 @@ typedef struct RTSPState {
>  
>      char default_lang[4];
>      int buffer_size;
> +
> +    /** The following are used for RTSPS streams */
> +    //@{
> +    char *ca_file;
> +    int verify;
> +    char *cert_file;
> +    char *key_file;
> +    //@}
>  } RTSPState;
>  
>  #define RTSP_FLAG_FILTER_SRC  0x1    /**< Filter incoming UDP packets -

I'm saying it again, but I thought passing such parameters via URL was
a deprecated idea. It also won't be able to handle all valid paths and
such.
Jay Oct. 16, 2016, 9:20 p.m. UTC | #2
This is the approach present in avformat/rtsp.c, but I can modify. What is
preferred?

For clarity, this patch does not copy url params from the `rtsps://` input.
It passes tls params provided as cmd line options to the `tls://` protocol
handler.

Personally, I would like tls negotiation to be recognized in the tcp
handler and the connection upgraded to tls. This would allow for `rtsp://`
schemes to work with tls - nice if you do not initially know the connection
is secure ( parity with gstreamer ). Unfortunately I am new to ffmpeg and
there is a lot of code to digest. It also does not address encrypted udp.

Let me know how best to proceed. Thank you.
Jay

On Sun, Oct 16, 2016 at 1:35 PM wm4 <nfxjfg@googlemail.com> wrote:

> On Sun, 16 Oct 2016 12:24:37 -0400
> jayridge@gmail.com wrote:
>
> > From: Jay Ridgeway <jayridge@gmail.com>
> >
> > Pass TLS args to support RTSPS. This patch requires TLS patch.
> > ---
> >  libavformat/rtsp.c | 19 ++++++++++++++++---
> >  libavformat/rtsp.h |  8 ++++++++
> >  2 files changed, 24 insertions(+), 3 deletions(-)
> >
> > diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
> > index c6292c5..53ecb6c 100644
> > --- a/libavformat/rtsp.c
> > +++ b/libavformat/rtsp.c
> > @@ -78,6 +78,7 @@
> >      { "reorder_queue_size", "set number of packets to buffer for
> handling of reordered packets", OFFSET(reordering_queue_size),
> AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC }, \
> >      { "buffer_size",        "Underlying protocol send/receive buffer
> size",                  OFFSET(buffer_size),           AV_OPT_TYPE_INT, {
> .i64 = -1 }, -1, INT_MAX, DEC|ENC } \
> >
> > +#define NONNULLSTR(s) (s ? s : "")
> >
> >  const AVOption ff_rtsp_options[] = {
> >      { "initial_pause",  "do not start playing the stream immediately",
> OFFSET(initial_pause), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
> > @@ -97,6 +98,10 @@ const AVOption ff_rtsp_options[] = {
> >      { "stimeout", "set timeout (in microseconds) of socket TCP I/O
> operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN,
> INT_MAX, DEC },
> >      COMMON_OPTS(),
> >      { "user-agent", "override User-Agent header", OFFSET(user_agent),
> AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC },
> > +    { "ca_file", "Certificate Authority database file",
> OFFSET(ca_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC|ENC },
> > +    { "tls_verify", "verify the peer certificate", OFFSET(verify),
> AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC|ENC},
> > +    { "cert_file", "certificate file", OFFSET(cert_file),
> AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC|ENC },
> > +    { "key_file", "private key file", OFFSET(key_file),
> AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC|ENC },
> >      { NULL },
> >  };
> >
> > @@ -1812,9 +1817,17 @@ redirect:
> >      } else {
> >          int ret;
> >          /* open the tcp connection */
> > -        ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL,
> > -                    host, port,
> > -                    "?timeout=%d", rt->stimeout);
> > +        if (strcmp("tls", lower_rtsp_proto) == 0) {
> > +            ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto,
> NULL,
> > +                        host, port,
> > +
> "?timeout=%d&verify=%d&cafile=%s&cert_file=%s&key_file=%s",
> > +                        rt->stimeout, rt->verify,
> NONNULLSTR(rt->ca_file),
> > +                        NONNULLSTR(rt->cert_file),
> NONNULLSTR(rt->key_file));
> > +        } else {
> > +            ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto,
> NULL,
> > +                        host, port,
> > +                        "?timeout=%d", rt->stimeout);
> > +        }
> >          if ((ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname,
> AVIO_FLAG_READ_WRITE,
> >                         &s->interrupt_callback, NULL,
> s->protocol_whitelist, s->protocol_blacklist, NULL)) < 0) {
> >              err = ret;
> > diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
> > index 852fd67..fa872a8 100644
> > --- a/libavformat/rtsp.h
> > +++ b/libavformat/rtsp.h
> > @@ -408,6 +408,14 @@ typedef struct RTSPState {
> >
> >      char default_lang[4];
> >      int buffer_size;
> > +
> > +    /** The following are used for RTSPS streams */
> > +    //@{
> > +    char *ca_file;
> > +    int verify;
> > +    char *cert_file;
> > +    char *key_file;
> > +    //@}
> >  } RTSPState;
> >
> >  #define RTSP_FLAG_FILTER_SRC  0x1    /**< Filter incoming UDP packets -
>
> I'm saying it again, but I thought passing such parameters via URL was
> a deprecated idea. It also won't be able to handle all valid paths and
> such.
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
wm4 Oct. 17, 2016, 10:08 a.m. UTC | #3
On Sun, 16 Oct 2016 21:20:04 +0000
Jay <jayridge@gmail.com> wrote:

> This is the approach present in avformat/rtsp.c, but I can modify. What is
> preferred?
> 
> For clarity, this patch does not copy url params from the `rtsps://` input.
> It passes tls params provided as cmd line options to the `tls://` protocol
> handler.
> 
> Personally, I would like tls negotiation to be recognized in the tcp
> handler and the connection upgraded to tls. This would allow for `rtsp://`
> schemes to work with tls - nice if you do not initially know the connection
> is secure ( parity with gstreamer ). Unfortunately I am new to ffmpeg and
> there is a lot of code to digest. It also does not address encrypted udp.
> 
> Let me know how best to proceed. Thank you.
> Jay

ffurl_open_whitelist() has an options parameter. This is a AVDictionary
that contains one option/value pair per entry. It _should_ be possible
to pass down the options you want to set with this, instead of
appending them to the URL. Although I haven't tried this myself, and
can't be sure there isn't something else that breaks this.
diff mbox

Patch

diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index c6292c5..53ecb6c 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -78,6 +78,7 @@ 
     { "reorder_queue_size", "set number of packets to buffer for handling of reordered packets", OFFSET(reordering_queue_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC }, \
     { "buffer_size",        "Underlying protocol send/receive buffer size",                  OFFSET(buffer_size),           AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC|ENC } \
 
+#define NONNULLSTR(s) (s ? s : "")
 
 const AVOption ff_rtsp_options[] = {
     { "initial_pause",  "do not start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
@@ -97,6 +98,10 @@  const AVOption ff_rtsp_options[] = {
     { "stimeout", "set timeout (in microseconds) of socket TCP I/O operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC },
     COMMON_OPTS(),
     { "user-agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC },
+    { "ca_file", "Certificate Authority database file", OFFSET(ca_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC|ENC },
+    { "tls_verify", "verify the peer certificate", OFFSET(verify), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC|ENC},
+    { "cert_file", "certificate file", OFFSET(cert_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC|ENC },
+    { "key_file", "private key file", OFFSET(key_file),  AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC|ENC },
     { NULL },
 };
 
@@ -1812,9 +1817,17 @@  redirect:
     } else {
         int ret;
         /* open the tcp connection */
-        ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL,
-                    host, port,
-                    "?timeout=%d", rt->stimeout);
+        if (strcmp("tls", lower_rtsp_proto) == 0) {
+            ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL,
+                        host, port,
+                        "?timeout=%d&verify=%d&cafile=%s&cert_file=%s&key_file=%s",
+                        rt->stimeout, rt->verify, NONNULLSTR(rt->ca_file),
+                        NONNULLSTR(rt->cert_file), NONNULLSTR(rt->key_file));
+        } else {
+            ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL,
+                        host, port,
+                        "?timeout=%d", rt->stimeout);
+        }
         if ((ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
                        &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL)) < 0) {
             err = ret;
diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
index 852fd67..fa872a8 100644
--- a/libavformat/rtsp.h
+++ b/libavformat/rtsp.h
@@ -408,6 +408,14 @@  typedef struct RTSPState {
 
     char default_lang[4];
     int buffer_size;
+
+    /** The following are used for RTSPS streams */
+    //@{
+    char *ca_file;
+    int verify;
+    char *cert_file;
+    char *key_file;
+    //@}
 } RTSPState;
 
 #define RTSP_FLAG_FILTER_SRC  0x1    /**< Filter incoming UDP packets -