[vlc-devel] [PATCH 1/4] chromecast: Refactor network interactions
Hugo Beauzée-Luyssen
hugo at beauzee.fr
Thu Mar 2 14:30:42 CET 2017
On Thu, Mar 2, 2017, at 02:23 PM, Rémi Denis-Courmont wrote:
> 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
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
Hi,
I thought it would be overkill to decrement the timeout each time data
is received/interrupt happens, though to be honest I don't know how the
chromecast will tolerate that. I can fix this, but I'm not sure how
worth it that is.
Regards,
--
Hugo Beauzée-Luyssen
hugo at beauzee.fr
More information about the vlc-devel
mailing list