[vlc-devel] [PATCH 1/4] chromecast: Refactor network interactions

Rémi Denis-Courmont remi at remlab.net
Thu Mar 2 14:23:32 CET 2017


On March 2, 2017 11:46:45 AM GMT+02:00, "Hugo Beauzée-Luyssen" <hugo at beauzee.fr> wrote:
>fix #18050
>---
> modules/stream_out/chromecast/chromecast.h         |  2 +-
>.../chromecast/chromecast_communication.cpp        | 79
>++++++++++------------
>modules/stream_out/chromecast/chromecast_ctrl.cpp  | 63
>++++++++++++-----
> 3 files changed, 81 insertions(+), 63 deletions(-)
>
>diff --git a/modules/stream_out/chromecast/chromecast.h
>b/modules/stream_out/chromecast/chromecast.h
>index d60e43e4b7..fe63ee4072 100644
>--- a/modules/stream_out/chromecast/chromecast.h
>+++ b/modules/stream_out/chromecast/chromecast.h
>@@ -113,7 +113,7 @@ public:
>                         const std::string & currentTime );
>void msgPlayerSetVolume( const std::string& destinationId, const
>std::string& mediaSessionId,
>                              float volume, bool mute);
>-    ssize_t recvPacket( uint8_t *p_data);
>+    ssize_t receive( uint8_t *p_data, size_t i_size, bool *pb_timeout
>);
> private:
>     int sendMessage(const castchannel::CastMessage &msg);
> 
>diff --git a/modules/stream_out/chromecast/chromecast_communication.cpp
>b/modules/stream_out/chromecast/chromecast_communication.cpp
>index d880a368e8..6331f6d336 100644
>--- a/modules/stream_out/chromecast/chromecast_communication.cpp
>+++ b/modules/stream_out/chromecast/chromecast_communication.cpp
>@@ -122,63 +122,54 @@ void ChromecastCommunication::buildMessage(const
>std::string & namespace_,
>* @param i_payloadSize returns the payload size of the message received
>  * @return the number of bytes received of -1 on error
>  */
>-ssize_t ChromecastCommunication::recvPacket( uint8_t *p_data )
>+ssize_t ChromecastCommunication::receive( uint8_t *p_data, size_t
>i_size, bool *pb_timeout )
> {
>-    ssize_t i_payloadSize = -1;
>+    ssize_t i_received = 0;
>     struct pollfd ufd[1];
>     ufd[0].fd = m_sock_fd;
>     ufd[0].events = POLLIN;
> 
>+    struct iovec iov;
>+    iov.iov_base = p_data;
>+    iov.iov_len = i_size;
>+
> /* The Chromecast normally sends a PING command every 5 seconds or so.
>      * If we do not receive one after 6 seconds, we send a PING.
>   * If after this PING, we do not receive a PONG, then we consider the
>      * connection as dead. */
>-    ssize_t val = vlc_poll_i11e(ufd, 1, PING_WAIT_TIME);
>-    if ( val == -1 )
>+    do
>     {
>-        if ( errno != EINTR )
>-            return -1;
>-        return 0;
>-    }
>-    if ( val == 0 )
>-        return 0;
>-
>-    if ( ufd[0].revents & POLLIN )
>-    {
>-        /* we have received stuff */
>-
>-        /* Packet structure:
>-         *
>+------------------------------------+------------------------------+
>-         * | Payload size (uint32_t big endian) |         Payload data
>        |
>-         *
>+------------------------------------+------------------------------+
>*/
>-        // We receive the header.
>-        ssize_t i_ret = vlc_tls_Read(m_tls, p_data, PACKET_HEADER_LEN,
>true);
>-        if (i_ret < PACKET_HEADER_LEN)
>-            return -1;
>-
>-        // We receive the payload.
>-
>-        // Get the size of the payload
>-        i_payloadSize = U32_AT( p_data );
>-        const uint32_t i_maxPayloadSize = PACKET_MAX_LEN -
>PACKET_HEADER_LEN;
>-
>-        if (i_payloadSize > i_maxPayloadSize)
>+        ssize_t i_ret = m_tls->readv( m_tls, &iov, 1 );
>+        if ( i_ret < 0 )
>         {
>-            // Error case: the packet sent by the Chromecast is too
>long: we drop it.
>-            msg_Err( m_module, "Packet too long: dropping its data");
>-
>-            i_ret = vlc_tls_Read(m_tls, p_data + PACKET_HEADER_LEN,
>-                                 i_maxPayloadSize, false);
>-            return i_ret ? i_ret : -1;
>+#ifdef _WIN32
>+            if ( WSAGetLastError() != WSAEWOULDBLOCK )
>+#else
>+            if ( errno != EAGAIN )
>+#endif
>+            {
>+                return -1;
>+            }
>+            ssize_t val = vlc_poll_i11e(ufd, 1, PING_WAIT_TIME);
>+            if ( val < 0 )
>+                return -1;
>+            else if ( val == 0 )
>+            {
>+                *pb_timeout = true;
>+                return i_received;
>+            }
>+            assert( ufd[0].revents & POLLIN );
>+            continue;
>         }
>-
>-        // Normal case
>-        i_ret = vlc_tls_Read(m_tls, p_data + PACKET_HEADER_LEN,
>i_payloadSize,
>-                             false);
>-        if (i_ret < i_payloadSize)
>+        else if ( i_ret == 0 )
>             return -1;
>-    }
>-    return i_payloadSize;
>+        assert( i_size >= (size_t)i_ret );
>+        i_size -= i_ret;
>+        i_received += i_ret;
>+        iov.iov_base = (uint8_t*)iov.iov_base + i_ret;
>+        iov.iov_len = i_size;
>+    } while ( i_size > 0 );
>+    return i_received;
> }
> 
> 
>diff --git a/modules/stream_out/chromecast/chromecast_ctrl.cpp
>b/modules/stream_out/chromecast/chromecast_ctrl.cpp
>index 292926b089..3434aa89a0 100644
>--- a/modules/stream_out/chromecast/chromecast_ctrl.cpp
>+++ b/modules/stream_out/chromecast/chromecast_ctrl.cpp
>@@ -538,7 +538,9 @@ void intf_sys_t::processConnectionMessage( const
>castchannel::CastMessage& msg )
> bool intf_sys_t::handleMessages()
> {
>     uint8_t p_packet[PACKET_MAX_LEN];
>-    ssize_t i_payloadSize = 0;
>+    size_t i_payloadSize = 0;
>+    size_t i_received = 0;
>+    bool b_timeout = false;
> 
>   if ( m_requested_stop.exchange(false) && !m_mediaSessionId.empty() )
>     {
>@@ -559,24 +561,32 @@ bool intf_sys_t::handleMessages()
>m_communication.msgPlayerSeek( m_appTransportId, m_mediaSessionId,
>current_time );
>     }
> 
>-    i_payloadSize = m_communication.recvPacket( p_packet );
>-#if defined(_WIN32)
>-    if ( i_payloadSize < 0 && WSAGetLastError() != WSAEWOULDBLOCK )
>-#else
>-    if ( i_payloadSize < 0 )
>-#endif
>-    {
>-        // An error occured, we give up
>-        msg_Err( m_module, "The connection to the Chromecast died
>(receiving).");
>-        vlc_mutex_locker locker(&m_lock);
>-        setState( Dead );
>-        return false;
>-    }
>-    if ( i_payloadSize == 0 )
>+    /* Packet structure:
>+     *
>+------------------------------------+------------------------------+
>+     * | Payload size (uint32_t big endian) |         Payload data    
>    |
>+     *
>+------------------------------------+------------------------------+
>+     */
>+    while ( true )
>     {
>-        // If no commands were queued to be sent, we timed out. Let's
>ping the chromecast
>-        if ( m_requested_seek == false && m_requested_stop == false )
>+        // If we haven't received the payload size yet, let's wait for
>it. Otherwise, we know
>+        // how much bytes to read
>+        ssize_t i_ret = m_communication.receive( p_packet +
>i_received,
>+                                         i_payloadSize +
>PACKET_HEADER_LEN - i_received,
>+                                         &b_timeout );
>+        if ( i_ret < 0 )
>+        {
>+            // If we need to process a command, let it happen at next
>iteration
>+            if ( errno == EINTR )
>+                return true;
>+            // An error occured, we give up
>+            msg_Err( m_module, "The connection to the Chromecast died
>(receiving).");
>+            vlc_mutex_locker locker(&m_lock);
>+            setState( Dead );
>+            return false;
>+        }
>+        else if ( b_timeout == true )
>         {
>+            // If no commands were queued to be sent, we timed out.
>Let's ping the chromecast
>             if ( m_pingRetriesLeft == 0 )
>             {
>                 vlc_mutex_locker locker(&m_lock);
>@@ -587,8 +597,25 @@ bool intf_sys_t::handleMessages()
>             --m_pingRetriesLeft;
>             m_communication.msgPing();
>             m_communication.msgReceiverGetStatus();
>+            return true;
>         }
>-        return true;
>+        assert( i_ret != 0 );
>+        i_received += i_ret;
>+        if ( i_payloadSize == 0 )
>+        {
>+            i_payloadSize = U32_AT( p_packet );
>+            if ( i_payloadSize > PACKET_MAX_LEN - PACKET_HEADER_LEN )
>+            {
>+                msg_Err( m_module, "Payload size is too long: dropping
>conection" );
>+                vlc_mutex_locker locker(&m_lock);
>+                m_state = Dead;
>+                return false;
>+            }
>+            continue;
>+        }
>+        assert( i_received <= i_payloadSize + PACKET_HEADER_LEN );
>+        if ( i_received == i_payloadSize + PACKET_HEADER_LEN )
>+            break;
>     }
>     castchannel::CastMessage msg;
>     msg.ParseFromArray(p_packet + PACKET_HEADER_LEN, i_payloadSize);
>-- 
>2.11.0
>
>_______________________________________________
>vlc-devel mailing list
>To unsubscribe or modify your subscription options:
>https://mailman.videolan.org/listinfo/vlc-devel

The time-out is reset at every interruption or partial read. I doubt that this would be correct.
-- 
Rémi Denis-Courmont


More information about the vlc-devel mailing list