[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