[vlc-devel] [PATCH 6/6] sout: chromecast: prevent conflict between multiple chromecasts

Filip Roséen filip at atch.se
Mon Jul 23 19:57:02 CEST 2018


In order for us to support streaming to more than one chromecast using
the same instance of libvlc (as through VLM), and with the same
options for the httpd, we will need to have a unique identifier for
each output.

These changes generates a random path upon initialization of the
relevant object, while also incorporating the current tick. There is
an extremely slim chance that two chromecast souts would try to create
the http bindings at the exact same time, but vlc_tick_now + a random
identifier is a "better safe than sorry" implementation.

In order to really dive down in the "better safe than sorry"-category,
we try three times before giving up.

fixes: #20380
fixes: #20890
---
 modules/stream_out/chromecast/chromecast.h    | 12 +++++-
 .../stream_out/chromecast/chromecast_ctrl.cpp | 40 ++++++++++++++++---
 2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/modules/stream_out/chromecast/chromecast.h b/modules/stream_out/chromecast/chromecast.h
index 01dd76ee24..4bd292b7c8 100644
--- a/modules/stream_out/chromecast/chromecast.h
+++ b/modules/stream_out/chromecast/chromecast.h
@@ -244,7 +244,6 @@ private:
 
 private:
     vlc_object_t  * const m_module;
-    const int      m_streaming_port;
     const int      m_device_port;
     std::string    m_mime;
     std::string    m_device_addr;
@@ -281,7 +280,16 @@ private:
 
     vlc_interrupt_t *m_ctl_thread_interrupt;
 
-    httpd_host_t     *m_httpd_host;
+    struct httpd_info_t {
+        httpd_info_t( httpd_host_t* host, int port );
+        ~httpd_info_t();
+
+        httpd_host_t *m_host;
+        int           m_port;
+        httpd_url_t  *m_url;
+        std::string   m_root;
+    } const m_httpd;
+
     httpd_file_t     *m_httpd_file;
     std::string       m_art_http_ip;
     char             *m_art_url;
diff --git a/modules/stream_out/chromecast/chromecast_ctrl.cpp b/modules/stream_out/chromecast/chromecast_ctrl.cpp
index 6f55fa3e23..5563a1d575 100644
--- a/modules/stream_out/chromecast/chromecast_ctrl.cpp
+++ b/modules/stream_out/chromecast/chromecast_ctrl.cpp
@@ -38,6 +38,7 @@
 #include <iomanip>
 
 #include <vlc_stream.h>
+#include <vlc_rand.h>
 
 #include "../../misc/webservices/json.h"
 
@@ -90,7 +91,6 @@ static const char* StateToStr( States s )
 intf_sys_t::intf_sys_t(vlc_object_t * const p_this, int port, std::string device_addr,
                        int device_port, httpd_host_t *httpd_host)
  : m_module(p_this)
- , m_streaming_port(port)
  , m_device_port(device_port)
  , m_device_addr(device_addr)
  , m_last_request_id( 0 )
@@ -109,7 +109,7 @@ intf_sys_t::intf_sys_t(vlc_object_t * const p_this, int port, std::string device
  , m_cc_eof( false )
  , m_pace( false )
  , m_meta( NULL )
- , m_httpd_host(httpd_host)
+ , m_httpd( httpd_host, port )
  , m_httpd_file(NULL)
  , m_art_url(NULL)
  , m_art_idx(0)
@@ -327,7 +327,7 @@ void intf_sys_t::prepareHttpArtwork()
 
         if( m_httpd_file )
             httpd_FileDelete( m_httpd_file );
-        m_httpd_file = httpd_FileNew( m_httpd_host, ss_art_idx.str().c_str(),
+        m_httpd_file = httpd_FileNew( m_httpd.m_host, ss_art_idx.str().c_str(),
                                       "application/octet-stream", NULL, NULL,
                                       httpd_file_fill_cb, (httpd_file_sys_t *) this );
 
@@ -584,6 +584,34 @@ void intf_sys_t::queueMessage( QueueableMessages msg )
     vlc_interrupt_raise( m_ctl_thread_interrupt );
 }
 
+intf_sys_t::httpd_info_t::httpd_info_t( httpd_host_t* host, int port )
+    : m_host( host )
+    , m_port( port )
+{
+    for( int i = 0; i < 3; ++i )
+    {
+        std::ostringstream ss;
+        ss << "/chromecast"
+           << "/" << vlc_tick_now()
+           << "/" << static_cast<uint64_t>( vlc_mrand48() );
+
+        m_root = ss.str();
+        m_url = httpd_UrlNew( m_host, m_root.c_str(), NULL, NULL );
+        if( m_url )
+            break;
+    }
+
+    if( m_url == NULL )
+        throw std::runtime_error( "unable to bind to http path" );
+}
+
+intf_sys_t::httpd_info_t::~httpd_info_t()
+
+{
+    if( m_url )
+        httpd_UrlDelete( m_url );
+}
+
 /*****************************************************************************
  * Chromecast thread
  *****************************************************************************/
@@ -1116,17 +1144,17 @@ vlc_tick_t intf_sys_t::getPauseDelay()
 
 unsigned int intf_sys_t::getHttpStreamPort() const
 {
-    return m_streaming_port;
+    return m_httpd.m_port;
 }
 
 std::string intf_sys_t::getHttpStreamPath() const
 {
-    return "/stream";
+    return m_httpd.m_root + "/stream";
 }
 
 std::string intf_sys_t::getHttpArtRoot() const
 {
-    return "/art";
+    return m_httpd.m_root + "/art";
 }
 
 bool intf_sys_t::isFinishedPlaying()
-- 
2.18.0


More information about the vlc-devel mailing list