Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
b613bad6
Commit
b613bad6
authored
Dec 23, 2015
by
Steve Lhomme
Committed by
Jean-Baptiste Kempf
Dec 23, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chromecast: move the packet receiver in the communication handler
Signed-off-by:
Jean-Baptiste Kempf
<
jb@videolan.org
>
parent
ad959d90
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
172 additions
and
169 deletions
+172
-169
modules/stream_out/chromecast/cast.cpp
modules/stream_out/chromecast/cast.cpp
+3
-168
modules/stream_out/chromecast/chromecast.h
modules/stream_out/chromecast/chromecast.h
+1
-0
modules/stream_out/chromecast/chromecast_ctrl.cpp
modules/stream_out/chromecast/chromecast_ctrl.cpp
+168
-1
No files found.
modules/stream_out/chromecast/cast.cpp
View file @
b613bad6
...
...
@@ -44,8 +44,6 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/coded_stream.h>
#define PACKET_MAX_LEN 10 * 1024
struct
sout_stream_sys_t
{
sout_stream_sys_t
(
intf_sys_t
*
intf
)
...
...
@@ -59,7 +57,6 @@ struct sout_stream_sys_t
delete
p_intf
;
}
int
i_sock_fd
;
vlc_tls_creds_t
*
p_creds
;
vlc_thread_t
chromecastThread
;
...
...
@@ -76,13 +73,6 @@ struct sout_stream_sys_t
#define SOUT_CFG_PREFIX "sout-chromecast-"
/* deadline regarding pings sent from receiver */
#define PING_WAIT_TIME 6000
#define PING_WAIT_RETRIES 0
/* deadline regarding pong we expect after pinging the receiver */
#define PONG_WAIT_TIME 500
#define PONG_WAIT_RETRIES 2
/*****************************************************************************
* Local prototypes
*****************************************************************************/
...
...
@@ -199,9 +189,9 @@ static int Open(vlc_object_t *p_this)
return
VLC_EGENERIC
;
}
p_sys
->
i_sock_fd
=
connectChromecast
(
p_stream
,
psz_ipChromecast
);
p_sys
->
p_intf
->
i_sock_fd
=
connectChromecast
(
p_stream
,
psz_ipChromecast
);
free
(
psz_ipChromecast
);
if
(
p_sys
->
i_sock_fd
<
0
)
if
(
p_sys
->
p_intf
->
i_sock_fd
<
0
)
{
msg_Err
(
p_stream
,
"Could not connect the Chromecast"
);
Clean
(
p_stream
);
...
...
@@ -210,7 +200,7 @@ static int Open(vlc_object_t *p_this)
p_sys
->
p_intf
->
setConnectionStatus
(
CHROMECAST_TLS_CONNECTED
);
char
psz_localIP
[
NI_MAXNUMERICHOST
];
if
(
net_GetSockAddress
(
p_sys
->
i_sock_fd
,
psz_localIP
,
NULL
))
if
(
net_GetSockAddress
(
p_sys
->
p_intf
->
i_sock_fd
,
psz_localIP
,
NULL
))
{
msg_Err
(
p_this
,
"Cannot get local IP address"
);
Clean
(
p_stream
);
...
...
@@ -388,118 +378,6 @@ static void disconnectChromecast(sout_stream_t *p_stream)
/**
* @brief Receive a data packet from the Chromecast
* @param p_stream the sout_stream_t structure
* @param b_msgReceived returns true if a message has been entirely received else false
* @param i_payloadSize returns the payload size of the message received
* @return the number of bytes received of -1 on error
*/
// Use here only C linkage and POD types as this function is a cancelation point.
extern
"C"
int
recvPacket
(
sout_stream_t
*
p_stream
,
bool
&
b_msgReceived
,
uint32_t
&
i_payloadSize
,
int
i_sock_fd
,
vlc_tls_t
*
p_tls
,
unsigned
*
pi_received
,
char
*
p_data
,
bool
*
pb_pingTimeout
,
int
*
pi_wait_delay
,
int
*
pi_wait_retries
)
{
struct
pollfd
ufd
[
1
];
ufd
[
0
].
fd
=
i_sock_fd
;
ufd
[
0
].
events
=
POLLIN
;
/* 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. */
if
(
poll
(
ufd
,
1
,
*
pi_wait_delay
)
==
0
)
{
if
(
*
pb_pingTimeout
)
{
if
(
!*
pi_wait_retries
)
{
msg_Err
(
p_stream
,
"No PONG answer received from the Chromecast"
);
return
0
;
// Connection died
}
(
*
pi_wait_retries
)
--
;
}
else
{
/* now expect a pong */
*
pi_wait_delay
=
PONG_WAIT_TIME
;
*
pi_wait_retries
=
PONG_WAIT_RETRIES
;
msg_Warn
(
p_stream
,
"No PING received from the Chromecast, sending a PING"
);
}
*
pb_pingTimeout
=
true
;
}
else
{
*
pb_pingTimeout
=
false
;
/* reset to default ping waiting */
*
pi_wait_delay
=
PING_WAIT_TIME
;
*
pi_wait_retries
=
PING_WAIT_RETRIES
;
}
int
i_ret
;
/* Packet structure:
* +------------------------------------+------------------------------+
* | Payload size (uint32_t big endian) | Payload data |
* +------------------------------------+------------------------------+ */
if
(
*
pi_received
<
PACKET_HEADER_LEN
)
{
// We receive the header.
i_ret
=
tls_Recv
(
p_tls
,
p_data
,
PACKET_HEADER_LEN
-
*
pi_received
);
if
(
i_ret
<=
0
)
return
i_ret
;
*
pi_received
+=
i_ret
;
}
else
{
// We receive the payload.
// Get the size of the payload
memcpy
(
&
i_payloadSize
,
p_data
,
PACKET_HEADER_LEN
);
i_payloadSize
=
hton32
(
i_payloadSize
);
const
uint32_t
i_maxPayloadSize
=
PACKET_MAX_LEN
-
PACKET_HEADER_LEN
;
if
(
i_payloadSize
>
i_maxPayloadSize
)
{
// Error case: the packet sent by the Chromecast is too long: we drop it.
msg_Err
(
p_stream
,
"Packet too long: droping its data"
);
uint32_t
i_size
=
i_payloadSize
-
(
*
pi_received
-
PACKET_HEADER_LEN
);
if
(
i_size
>
i_maxPayloadSize
)
i_size
=
i_maxPayloadSize
;
i_ret
=
tls_Recv
(
p_tls
,
p_data
+
PACKET_HEADER_LEN
,
i_size
);
if
(
i_ret
<=
0
)
return
i_ret
;
*
pi_received
+=
i_ret
;
if
(
*
pi_received
<
i_payloadSize
+
PACKET_HEADER_LEN
)
return
i_ret
;
*
pi_received
=
0
;
return
-
1
;
}
// Normal case
i_ret
=
tls_Recv
(
p_tls
,
p_data
+
*
pi_received
,
i_payloadSize
-
(
*
pi_received
-
PACKET_HEADER_LEN
));
if
(
i_ret
<=
0
)
return
i_ret
;
*
pi_received
+=
i_ret
;
if
(
*
pi_received
<
i_payloadSize
+
PACKET_HEADER_LEN
)
return
i_ret
;
assert
(
*
pi_received
==
i_payloadSize
+
PACKET_HEADER_LEN
);
*
pi_received
=
0
;
b_msgReceived
=
true
;
return
i_ret
;
}
return
i_ret
;
}
/*****************************************************************************
* Chromecast thread
...
...
@@ -511,53 +389,12 @@ static void* chromecastThread(void* p_data)
sout_stream_t
*
p_stream
=
reinterpret_cast
<
sout_stream_t
*>
(
p_data
);
sout_stream_sys_t
*
p_sys
=
p_stream
->
p_sys
;
unsigned
i_received
=
0
;
char
p_packet
[
PACKET_MAX_LEN
];
bool
b_pingTimeout
=
false
;
int
i_waitdelay
=
PING_WAIT_TIME
;
int
i_retries
=
PING_WAIT_RETRIES
;
p_sys
->
p_intf
->
msgAuth
();
p_sys
->
p_intf
->
sendMessages
();
vlc_restorecancel
(
canc
);
while
(
1
)
{
bool
b_msgReceived
=
false
;
uint32_t
i_payloadSize
=
0
;
int
i_ret
=
recvPacket
(
p_stream
,
b_msgReceived
,
i_payloadSize
,
p_sys
->
i_sock_fd
,
p_sys
->
p_intf
->
p_tls
,
&
i_received
,
p_packet
,
&
b_pingTimeout
,
&
i_waitdelay
,
&
i_retries
);
canc
=
vlc_savecancel
();
// Not cancellation-safe part.
#if defined(_WIN32)
if
((
i_ret
<
0
&&
WSAGetLastError
()
!=
WSAEWOULDBLOCK
)
||
(
i_ret
==
0
))
#else
if
((
i_ret
<
0
&&
errno
!=
EAGAIN
)
||
i_ret
==
0
)
#endif
{
msg_Err
(
p_stream
,
"The connection to the Chromecast died."
);
vlc_mutex_locker
locker
(
&
p_sys
->
p_intf
->
lock
);
p_sys
->
p_intf
->
setConnectionStatus
(
CHROMECAST_CONNECTION_DEAD
);
break
;
}
if
(
b_pingTimeout
)
{
p_sys
->
p_intf
->
msgPing
();
p_sys
->
p_intf
->
msgReceiverGetStatus
();
}
if
(
b_msgReceived
)
{
castchannel
::
CastMessage
msg
;
msg
.
ParseFromArray
(
p_packet
+
PACKET_HEADER_LEN
,
i_payloadSize
);
p_sys
->
p_intf
->
processMessage
(
msg
);
}
p_sys
->
p_intf
->
handleMessages
();
vlc_mutex_lock
(
&
p_sys
->
p_intf
->
lock
);
...
...
@@ -567,8 +404,6 @@ static void* chromecastThread(void* p_data)
break
;
}
vlc_mutex_unlock
(
&
p_sys
->
p_intf
->
lock
);
vlc_restorecancel
(
canc
);
}
return
NULL
;
...
...
modules/stream_out/chromecast/chromecast.h
View file @
b613bad6
...
...
@@ -66,6 +66,7 @@ struct intf_sys_t
std
::
string
serverIP
;
std
::
string
appTransportId
;
int
i_sock_fd
;
vlc_tls_t
*
p_tls
;
vlc_mutex_t
lock
;
...
...
modules/stream_out/chromecast/chromecast_ctrl.cpp
View file @
b613bad6
...
...
@@ -35,12 +35,24 @@
#include <vlc_sout.h>
#include <sstream>
#ifdef HAVE_POLL
# include <poll.h>
#endif
#include "../../misc/webservices/json.h"
#define PACKET_MAX_LEN 10 * 1024
// Media player Chromecast app id
#define APP_ID "CC1AD845" // Default media player aka DEFAULT_MEDIA_RECEIVER_APPLICATION_ID
/* deadline regarding pings sent from receiver */
#define PING_WAIT_TIME 6000
#define PING_WAIT_RETRIES 0
/* deadline regarding pong we expect after pinging the receiver */
#define PONG_WAIT_TIME 500
#define PONG_WAIT_RETRIES 2
#define SOUT_CFG_PREFIX "sout-chromecast-"
static
const
std
::
string
NAMESPACE_DEVICEAUTH
=
"urn:x-cast:com.google.cast.tp.deviceauth"
;
...
...
@@ -94,6 +106,118 @@ intf_sys_t::~intf_sys_t()
vlc_mutex_destroy
(
&
lock
);
}
/**
* @brief Receive a data packet from the Chromecast
* @param p_stream the sout_stream_t structure
* @param b_msgReceived returns true if a message has been entirely received else false
* @param i_payloadSize returns the payload size of the message received
* @return the number of bytes received of -1 on error
*/
// Use here only C linkage and POD types as this function is a cancelation point.
extern
"C"
int
recvPacket
(
sout_stream_t
*
p_stream
,
bool
&
b_msgReceived
,
uint32_t
&
i_payloadSize
,
int
i_sock_fd
,
vlc_tls_t
*
p_tls
,
unsigned
*
pi_received
,
char
*
p_data
,
bool
*
pb_pingTimeout
,
int
*
pi_wait_delay
,
int
*
pi_wait_retries
)
{
struct
pollfd
ufd
[
1
];
ufd
[
0
].
fd
=
i_sock_fd
;
ufd
[
0
].
events
=
POLLIN
;
/* 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. */
if
(
poll
(
ufd
,
1
,
*
pi_wait_delay
)
==
0
)
{
if
(
*
pb_pingTimeout
)
{
if
(
!*
pi_wait_retries
)
{
msg_Err
(
p_stream
,
"No PONG answer received from the Chromecast"
);
return
0
;
// Connection died
}
(
*
pi_wait_retries
)
--
;
}
else
{
/* now expect a pong */
*
pi_wait_delay
=
PONG_WAIT_TIME
;
*
pi_wait_retries
=
PONG_WAIT_RETRIES
;
msg_Warn
(
p_stream
,
"No PING received from the Chromecast, sending a PING"
);
}
*
pb_pingTimeout
=
true
;
}
else
{
*
pb_pingTimeout
=
false
;
/* reset to default ping waiting */
*
pi_wait_delay
=
PING_WAIT_TIME
;
*
pi_wait_retries
=
PING_WAIT_RETRIES
;
}
int
i_ret
;
/* Packet structure:
* +------------------------------------+------------------------------+
* | Payload size (uint32_t big endian) | Payload data |
* +------------------------------------+------------------------------+ */
if
(
*
pi_received
<
PACKET_HEADER_LEN
)
{
// We receive the header.
i_ret
=
tls_Recv
(
p_tls
,
p_data
,
PACKET_HEADER_LEN
-
*
pi_received
);
if
(
i_ret
<=
0
)
return
i_ret
;
*
pi_received
+=
i_ret
;
}
else
{
// We receive the payload.
// Get the size of the payload
memcpy
(
&
i_payloadSize
,
p_data
,
PACKET_HEADER_LEN
);
i_payloadSize
=
hton32
(
i_payloadSize
);
const
uint32_t
i_maxPayloadSize
=
PACKET_MAX_LEN
-
PACKET_HEADER_LEN
;
if
(
i_payloadSize
>
i_maxPayloadSize
)
{
// Error case: the packet sent by the Chromecast is too long: we drop it.
msg_Err
(
p_stream
,
"Packet too long: droping its data"
);
uint32_t
i_size
=
i_payloadSize
-
(
*
pi_received
-
PACKET_HEADER_LEN
);
if
(
i_size
>
i_maxPayloadSize
)
i_size
=
i_maxPayloadSize
;
i_ret
=
tls_Recv
(
p_tls
,
p_data
+
PACKET_HEADER_LEN
,
i_size
);
if
(
i_ret
<=
0
)
return
i_ret
;
*
pi_received
+=
i_ret
;
if
(
*
pi_received
<
i_payloadSize
+
PACKET_HEADER_LEN
)
return
i_ret
;
*
pi_received
=
0
;
return
-
1
;
}
// Normal case
i_ret
=
tls_Recv
(
p_tls
,
p_data
+
*
pi_received
,
i_payloadSize
-
(
*
pi_received
-
PACKET_HEADER_LEN
));
if
(
i_ret
<=
0
)
return
i_ret
;
*
pi_received
+=
i_ret
;
if
(
*
pi_received
<
i_payloadSize
+
PACKET_HEADER_LEN
)
return
i_ret
;
assert
(
*
pi_received
==
i_payloadSize
+
PACKET_HEADER_LEN
);
*
pi_received
=
0
;
b_msgReceived
=
true
;
return
i_ret
;
}
return
i_ret
;
}
/**
* @brief Process a message received from the Chromecast
* @param msg the CastMessage to process
...
...
@@ -384,7 +508,48 @@ int intf_sys_t::sendMessages()
void
intf_sys_t
::
handleMessages
()
{
int
i_ret
;
unsigned
i_received
=
0
;
char
p_packet
[
PACKET_MAX_LEN
];
bool
b_pingTimeout
=
false
;
int
i_waitdelay
=
PING_WAIT_TIME
;
int
i_retries
=
PING_WAIT_RETRIES
;
bool
b_msgReceived
=
false
;
uint32_t
i_payloadSize
=
0
;
int
i_ret
=
recvPacket
(
p_stream
,
b_msgReceived
,
i_payloadSize
,
i_sock_fd
,
p_tls
,
&
i_received
,
p_packet
,
&
b_pingTimeout
,
&
i_waitdelay
,
&
i_retries
);
int
canc
=
vlc_savecancel
();
// Not cancellation-safe part.
#if defined(_WIN32)
if
((
i_ret
<
0
&&
WSAGetLastError
()
!=
WSAEWOULDBLOCK
)
||
(
i_ret
==
0
))
#else
if
((
i_ret
<
0
&&
errno
!=
EAGAIN
)
||
i_ret
==
0
)
#endif
{
msg_Err
(
p_stream
,
"The connection to the Chromecast died."
);
vlc_mutex_locker
locker
(
&
lock
);
setConnectionStatus
(
CHROMECAST_CONNECTION_DEAD
);
vlc_restorecancel
(
canc
);
return
;
}
if
(
b_pingTimeout
)
{
msgPing
();
msgReceiverGetStatus
();
}
if
(
b_msgReceived
)
{
castchannel
::
CastMessage
msg
;
msg
.
ParseFromArray
(
p_packet
+
PACKET_HEADER_LEN
,
i_payloadSize
);
processMessage
(
msg
);
}
// Send the answer messages if there is any.
if
(
!
messagesToSend
.
empty
())
{
...
...
@@ -400,4 +565,6 @@ void intf_sys_t::handleMessages()
setConnectionStatus
(
CHROMECAST_CONNECTION_DEAD
);
}
}
vlc_restorecancel
(
canc
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment