[gnome-network-displays/cc-tmp: 20/80] cc: fix crash on cancel cast
- From: Benjamin Berg <bberg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-network-displays/cc-tmp: 20/80] cc: fix crash on cancel cast
- Date: Fri, 9 Sep 2022 12:03:49 +0000 (UTC)
commit ecf89d285b8c437ed85083217c24287220f92f05
Author: Anupam Kumar <kyteinsky gmail com>
Date: Sat Aug 6 17:43:14 2022 +0530
cc: fix crash on cancel cast
src/cc/cc-comm.c | 495 +++++++++++++++++++++++++++----------------------------
src/cc/cc-comm.h | 19 ++-
src/nd-cc-sink.c | 124 +++++++-------
3 files changed, 322 insertions(+), 316 deletions(-)
---
diff --git a/src/cc/cc-comm.c b/src/cc/cc-comm.c
index 03d45bd..d02b141 100644
--- a/src/cc/cc-comm.c
+++ b/src/cc/cc-comm.c
@@ -23,16 +23,16 @@
// function decl
static void cc_comm_listen (CcComm *comm);
-static void cc_comm_read (CcComm *comm, gsize io_bytes, gboolean read_header);
+static void cc_comm_read (CcComm *comm,
+ gsize io_bytes,
+ gboolean read_header);
static gboolean
cc_comm_load_media_cb (CcComm *comm)
{
if (!cc_comm_send_request (comm, MESSAGE_TYPE_MEDIA, "{ \"type\": \"LOAD\", \"media\": { \"contentId\":
\"https://commondatastorage.googleapis.com/gtv-videos-bucket/CastVideos/mp4/BigBuckBunny.mp4\",
\"streamType\": \"BUFFERED\", \"contentType\": \"video/mp4\" }, \"requestId\": 4 }", NULL))
- {
g_warning ("NdCCSink: something went wrong with load media");
- }
return FALSE;
}
@@ -75,15 +75,15 @@ static gboolean
cc_comm_parse_json_data (CcComm *comm, char *payload)
{
g_autoptr(GError) error = NULL;
- g_autoptr(JsonParser) parser;
- g_autoptr(JsonReader) reader;
+ g_autoptr(JsonParser) parser = NULL;
+ g_autoptr(JsonReader) reader = NULL;
parser = json_parser_new ();
if (!json_parser_load_from_data (parser, payload, -1, &error))
- {
- g_warning ("NdCCSink: Error parsing received messaage JSON: %s", error->message);
- return TRUE;
- }
+ {
+ g_warning ("NdCCSink: Error parsing received messaage JSON: %s", error->message);
+ return TRUE;
+ }
reader = json_reader_new (json_parser_get_root (parser));
@@ -92,66 +92,69 @@ cc_comm_parse_json_data (CcComm *comm, char *payload)
json_reader_end_member (reader);
if (g_strcmp0 (message_type, "PONG") == 0)
- {
return FALSE;
- }
if (g_strcmp0 (message_type, "RECEIVER_STATUS") == 0)
- {
- if (!json_reader_read_member (reader, "status")) goto exit_parse;
- if (!json_reader_read_member (reader, "applications")) goto exit_parse;
- if (!json_reader_read_element (reader, 0)) goto exit_parse;
- if (!json_reader_read_member (reader, "appId")) goto exit_parse;
- const char *app_id = json_reader_get_string_value (reader);
- if (g_strcmp0 (app_id, "CC1AD845") == 0)
+ {
+ if (json_reader_read_member (reader, "status"))
+ {
+ if (json_reader_read_member (reader, "applications"))
{
+ if (json_reader_read_element (reader, 0))
+ {
+ if (json_reader_read_member (reader, "appId"))
+ {
+ const char *app_id = json_reader_get_string_value (reader);
+ if (g_strcmp0 (app_id, "CC1AD845") == 0)
+ {
+ json_reader_end_member (reader);
+ json_reader_read_member (reader, "transportId");
+ const char *transport_id = json_reader_get_string_value (reader);
+ g_debug ("CcComm: Transport Id: %s!", transport_id);
+
+ // start a new virtual connection
+ comm->destination_id = g_strdup (transport_id);
+ g_debug ("CcComm: Sending second connect request");
+ if (!cc_comm_send_request (comm, MESSAGE_TYPE_CONNECT, NULL, NULL))
+ {
+ g_warning ("CcComm: Something went wrong with VC request for media");
+ return TRUE;
+ }
+ // call the LOAD media request after 2 seconds
+ g_timeout_add_seconds (2, G_SOURCE_FUNC (cc_comm_load_media_cb), comm);
+ }
+ json_reader_end_member (reader);
+ }
+ json_reader_end_element (reader);
+ }
json_reader_end_member (reader);
- json_reader_read_member (reader, "transportId");
- const char *transport_id = json_reader_get_string_value (reader);
- g_debug ("CcComm: Transport Id: %s!", transport_id);
-
- // start a new virtual connection
- comm->destination_id = g_strdup (transport_id);
- // g_clear_pointer (&comm->sender_id, g_free);
- // comm->sender_id = g_strdup ("sender-gnd");
- g_debug ("CcComm: Sending second connect request");
- if (!cc_comm_send_request(comm, MESSAGE_TYPE_CONNECT, NULL, NULL))
- {
- g_warning ("CcComm: Something went wrong with VC request for media");
- return TRUE;
- }
- // call the LOAD media request after 4 seconds
- g_timeout_add_seconds (4, G_SOURCE_FUNC (cc_comm_load_media_cb), comm);
}
json_reader_end_member (reader);
- json_reader_end_element (reader);
- json_reader_end_member (reader);
- json_reader_end_member (reader);
- }
+ }
+ }
-exit_parse:
return TRUE;
}
static void
-cc_comm_parse_received_data(CcComm *comm, uint8_t * input_buffer, gssize input_size)
+cc_comm_parse_received_data (CcComm *comm, uint8_t * input_buffer, gssize input_size)
{
Castchannel__CastMessage *message;
- message = castchannel__cast_message__unpack(NULL, input_size, input_buffer);
+ message = castchannel__cast_message__unpack (NULL, input_size, input_buffer);
if (message == NULL)
- {
- g_warning ("CcComm: Failed to unpack received data");
- return;
- }
+ {
+ g_warning ("CcComm: Failed to unpack received data");
+ return;
+ }
if (cc_comm_parse_json_data (comm, message->payload_utf8))
- {
- g_debug("CcComm: Received data:");
- cc_comm_dump_json_message (message);
- }
+ {
+ g_debug ("CcComm: Received message:");
+ cc_comm_dump_json_message (message);
+ }
- castchannel__cast_message__free_unpacked(message, NULL);
+ castchannel__cast_message__free_unpacked (message, NULL);
}
static gboolean
@@ -183,19 +186,17 @@ cc_comm_accept_certificate (GTlsClientConnection *conn,
static guint32
cc_comm_to_message_size (CcComm *comm)
{
- return (guint32) (comm->header_buffer[0] * pow(256, 3) +
- comm->header_buffer[1] * pow(256, 2) +
- comm->header_buffer[2] * pow(256, 1) +
- comm->header_buffer[3] * pow(256, 0));
+ return GINT32_FROM_BE (*(guint32 *) comm->header_buffer);
}
// async callback for message read
static void
-cc_comm_message_read_cb (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
+cc_comm_message_read_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
{
- CcComm * comm = (CcComm*) user_data;
+ CcComm * comm = (CcComm *) user_data;
+
g_autoptr(GError) error = NULL;
gboolean success;
gsize io_bytes;
@@ -212,25 +213,25 @@ cc_comm_message_read_cb (GObject *source_object,
* then just give up immediately with a CLOSED error.
*/
if (comm->con &&
- g_io_stream_get_input_stream (G_IO_STREAM (comm->con)) != G_INPUT_STREAM (source_object))
- {
- g_error ("CcComm: Error on old read connection, ignoring.");
- cc_comm_listen (comm);
- return;
- }
+ g_io_stream_get_input_stream (G_IO_STREAM (comm->con)) != G_INPUT_STREAM (source_object))
+ {
+ g_error ("CcComm: Error on old read connection, ignoring.");
+ // cc_comm_listen (comm);
+ return;
+ }
if (!success || io_bytes == 0)
- {
- if (error)
{
- g_error ("CcComm: Error reading message from stream: %s", error->message);
+ if (error)
+ {
+ g_error ("CcComm: Error reading message from stream: %s", error->message);
+ cc_comm_listen (comm);
+ return;
+ }
+ g_error ("CcComm: Error reading message from stream.");
cc_comm_listen (comm);
return;
}
- g_error ("CcComm: Error reading message from stream.");
- cc_comm_listen (comm);
- return;
- }
// dump the received message and try to parse it
// cc_comm_dump_message (comm->message_buffer, io_bytes);
@@ -239,16 +240,17 @@ cc_comm_message_read_cb (GObject *source_object,
g_clear_pointer (&comm->message_buffer, g_free);
// go for another round
- cc_comm_listen(comm);
+ cc_comm_listen (comm);
}
// async callback for header read
static void
-cc_comm_header_read_cb (GObject *source_object,
+cc_comm_header_read_cb (GObject *source_object,
GAsyncResult *res,
- gpointer user_data)
+ gpointer user_data)
{
- CcComm * comm = (CcComm*) user_data;
+ CcComm * comm = (CcComm *) user_data;
+
g_autoptr(GError) error = NULL;
gboolean success;
gsize io_bytes;
@@ -266,25 +268,25 @@ cc_comm_header_read_cb (GObject *source_object,
* then just give up immediately with a CLOSED error.
*/
if (comm->con &&
- g_io_stream_get_input_stream (G_IO_STREAM (comm->con)) != G_INPUT_STREAM (source_object))
- {
- g_error ("CcComm: Error on old read connection, ignoring.");
- cc_comm_listen (comm);
- return;
- }
+ g_io_stream_get_input_stream (G_IO_STREAM (comm->con)) != G_INPUT_STREAM (source_object))
+ {
+ g_error ("CcComm: Error on old read connection, ignoring.");
+ cc_comm_listen (comm);
+ return;
+ }
if (!success || io_bytes != 4)
- {
- if (error)
{
- g_error ("CcComm: Error reading header from stream: %s", error->message);
+ if (error)
+ {
+ g_error ("CcComm: Error reading header from stream: %s", error->message);
+ cc_comm_listen (comm);
+ return;
+ }
+ g_error ("CcComm: Error reading header from stream.");
cc_comm_listen (comm);
return;
}
- g_error ("CcComm: Error reading header from stream.");
- cc_comm_listen (comm);
- return;
- }
// if everything is well, read all `io_bytes`
g_debug ("CcComm: Raw header dump:");
@@ -309,21 +311,21 @@ cc_comm_read (CcComm *comm, gsize io_bytes, gboolean read_header)
if (read_header)
{
g_input_stream_read_all_async (istream,
- comm->header_buffer,
- io_bytes,
- G_PRIORITY_DEFAULT,
- NULL,
- cc_comm_header_read_cb,
- comm);
+ comm->header_buffer,
+ io_bytes,
+ G_PRIORITY_DEFAULT,
+ comm->cancellable,
+ cc_comm_header_read_cb,
+ comm);
return;
}
g_input_stream_read_all_async (istream,
- comm->message_buffer,
- io_bytes,
- G_PRIORITY_DEFAULT,
- NULL,
- cc_comm_message_read_cb,
- comm);
+ comm->message_buffer,
+ io_bytes,
+ G_PRIORITY_DEFAULT,
+ comm->cancellable,
+ cc_comm_message_read_cb,
+ comm);
}
// listen to all incoming messages from Chromecast
@@ -355,49 +357,49 @@ cc_comm_make_connection (CcComm *comm, gchar *remote_address, GError **error)
socket_family = G_SOCKET_FAMILY_IPV4;
socket = g_socket_new (socket_family, socket_type, G_SOCKET_PROTOCOL_DEFAULT, error);
if (socket == NULL)
- {
- g_warning ("CcComm: Failed to create socket: %s", (*error)->message);
- return FALSE;
- }
+ {
+ g_warning ("CcComm: Failed to create socket: %s", (*error)->message);
+ return FALSE;
+ }
// XXX
// g_socket_set_timeout (socket, 10);
connectable = g_network_address_parse (remote_address, 8009, error);
if (connectable == NULL)
- {
- g_warning ("CcComm: Failed to create connectable: %s", (*error)->message);
- return FALSE;
- }
+ {
+ g_warning ("CcComm: Failed to create connectable: %s", (*error)->message);
+ return FALSE;
+ }
enumerator = g_socket_connectable_enumerate (connectable);
while (TRUE)
- {
- address = g_socket_address_enumerator_next (enumerator, NULL, error);
- if (address == NULL)
{
- g_warning ("CcComm: Failed to create address: %s", (*error)->message);
- return FALSE;
- }
+ address = g_socket_address_enumerator_next (enumerator, comm->cancellable, error);
+ if (address == NULL)
+ {
+ g_warning ("CcComm: Failed to create address: %s", (*error)->message);
+ return FALSE;
+ }
- if (g_socket_connect (socket, address, NULL, &err))
- break;
+ if (g_socket_connect (socket, address, comm->cancellable, &err))
+ break;
- // g_message ("Connection to %s failed: %s, trying next", socket_address_to_string (address),
err->message);
- g_clear_error (&err);
+ // g_message ("Connection to %s failed: %s, trying next", socket_address_to_string (address),
err->message);
+ g_clear_error (&err);
- g_object_unref (address);
- }
+ g_object_unref (address);
+ }
g_object_unref (enumerator);
comm->con = G_IO_STREAM (g_socket_connection_factory_create_connection (socket));
tls_conn = g_tls_client_connection_new (comm->con, connectable, error);
if (tls_conn == NULL)
- {
- g_warning ("CcComm: Failed to create TLS connection: %s", (*error)->message);
- return FALSE;
- }
+ {
+ g_warning ("CcComm: Failed to create TLS connection: %s", (*error)->message);
+ return FALSE;
+ }
g_signal_connect (tls_conn, "accept-certificate", G_CALLBACK (cc_comm_accept_certificate), NULL);
g_object_unref (comm->con);
@@ -405,11 +407,11 @@ cc_comm_make_connection (CcComm *comm, gchar *remote_address, GError **error)
comm->con = G_IO_STREAM (tls_conn);
// see what should be done about cancellable
- if (!g_tls_connection_handshake (G_TLS_CONNECTION (tls_conn), NULL, error))
- {
- g_warning ("CcComm: Failed to handshake: %s", (*error)->message);
- return FALSE;
- }
+ if (!g_tls_connection_handshake (G_TLS_CONNECTION (tls_conn), comm->cancellable, error))
+ {
+ g_warning ("CcComm: Failed to handshake: %s", (*error)->message);
+ return FALSE;
+ }
g_debug ("CcComm: Connected to %s", remote_address);
@@ -420,10 +422,10 @@ cc_comm_make_connection (CcComm *comm, gchar *remote_address, GError **error)
}
static gboolean
-cc_comm_tls_send (CcComm * comm,
- uint8_t * message,
- gssize size,
- GError **error)
+cc_comm_tls_send (CcComm * comm,
+ uint8_t * message,
+ gssize size,
+ GError **error)
{
GOutputStream *ostream;
gssize io_bytes;
@@ -442,53 +444,54 @@ cc_comm_tls_send (CcComm * comm,
// start sending data synchronously
while (size > 0)
- {
- io_bytes = g_output_stream_write (ostream, message, size, NULL, error);
-
- if (io_bytes <= 0)
{
- g_warning ("CcComm: Failed to write: %s", (*error)->message);
- g_clear_error (error);
- return FALSE;
- }
+ io_bytes = g_output_stream_write (ostream, message, size, comm->cancellable, error);
- g_debug ("CcComm: Sent %" G_GSSIZE_FORMAT " bytes", io_bytes);
+ if (io_bytes <= 0)
+ {
+ g_warning ("CcComm: Failed to write: %s", (*error)->message);
+ g_clear_error (error);
+ return FALSE;
+ }
+
+ // g_debug ("CcComm: Sent %" G_GSSIZE_FORMAT " bytes", io_bytes);
- size -= io_bytes;
- }
+ size -= io_bytes;
+ }
return TRUE;
}
// builds message based on available types
static Castchannel__CastMessage
-cc_comm_build_message (gchar *source_id,
- gchar *namespace_,
+cc_comm_build_message (gchar *namespace_,
Castchannel__CastMessage__PayloadType payload_type,
- ProtobufCBinaryData * binary_payload,
- gchar *utf8_payload)
+ ProtobufCBinaryData * binary_payload,
+ gchar *utf8_payload)
{
Castchannel__CastMessage message;
- castchannel__cast_message__init(&message);
+
+ castchannel__cast_message__init (&message);
message.protocol_version = CASTCHANNEL__CAST_MESSAGE__PROTOCOL_VERSION__CASTV2_1_0;
- message.source_id = source_id;
+ message.source_id = "sender-gnd";
message.destination_id = "receiver-0";
message.namespace_ = namespace_;
message.payload_type = payload_type;
switch (payload_type)
- {
- case CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__BINARY:
- message.payload_binary = *binary_payload;
- message.has_payload_binary = 1;
- break;
- case CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING:
- default:
- message.payload_utf8 = utf8_payload;
- message.has_payload_binary = 0;
- break;
- }
+ {
+ case CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__BINARY:
+ message.payload_binary = *binary_payload;
+ message.has_payload_binary = 1;
+ break;
+
+ case CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING:
+ default:
+ message.payload_utf8 = utf8_payload;
+ message.has_payload_binary = 0;
+ break;
+ }
return message;
}
@@ -501,97 +504,91 @@ cc_comm_send_request (CcComm * comm, enum MessageType message_type, char *utf8_p
g_autofree uint8_t *sock_buffer = NULL;
switch (message_type)
- {
- case MESSAGE_TYPE_AUTH:
- ProtobufCBinaryData binary_payload;
- binary_payload.data = NULL;
- binary_payload.len = 0;
-
- message = cc_comm_build_message(
- comm->sender_id,
- "urn:x-cast:com.google.cast.tp.deviceauth",
- CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__BINARY,
- &binary_payload,
- NULL);
- break;
-
- case MESSAGE_TYPE_CONNECT:
- message = cc_comm_build_message(
- comm->sender_id,
- "urn:x-cast:com.google.cast.tp.connection",
- CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
- NULL,
- // "{ \"type\": \"CONNECT\" }");
- "{ \"type\": \"CONNECT\", \"userAgent\": \"GND/0.90.5 (X11; Linux x86_64)\", \"connType\": 0,
\"origin\": {}, \"senderInfo\": { \"sdkType\": 2, \"version\": \"X11; Linux x86_64\", \"browserVersion\":
\"X11; Linux x86_64\", \"platform\": 6, \"connectionType\": 1 } }");
+ {
+ case MESSAGE_TYPE_AUTH:
+ ProtobufCBinaryData binary_payload;
+ binary_payload.data = NULL;
+ binary_payload.len = 0;
+
+ message = cc_comm_build_message (
+ "urn:x-cast:com.google.cast.tp.deviceauth",
+ CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__BINARY,
+ &binary_payload,
+ NULL);
+ break;
+
+ case MESSAGE_TYPE_CONNECT:
+ message = cc_comm_build_message (
+ "urn:x-cast:com.google.cast.tp.connection",
+ CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
+ NULL,
+ // "{ \"type\": \"CONNECT\" }");
+ "{ \"type\": \"CONNECT\", \"userAgent\": \"GND/0.90.5 (X11; Linux x86_64)\", \"connType\": 0,
\"origin\": {}, \"senderInfo\": { \"sdkType\": 2, \"version\": \"X11; Linux x86_64\", \"browserVersion\":
\"X11; Linux x86_64\", \"platform\": 6, \"connectionType\": 1 } }");
message.destination_id = comm->destination_id;
- break;
-
- case MESSAGE_TYPE_DISCONNECT:
- message = cc_comm_build_message(
- comm->sender_id,
- "urn:x-cast:com.google.cast.tp.connection",
- CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
- NULL,
- "{ \"type\": \"CLOSE\" }");
- break;
-
- case MESSAGE_TYPE_PING:
- message = cc_comm_build_message(
- comm->sender_id,
- "urn:x-cast:com.google.cast.tp.heartbeat",
- CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
- NULL,
- "{ \"type\": \"PING\" }");
- break;
-
- case MESSAGE_TYPE_PONG:
- message = cc_comm_build_message(
- comm->sender_id,
- "urn:x-cast:com.google.cast.tp.heartbeat",
- CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
- NULL,
- "{ \"type\": \"PONG\" }");
- break;
-
- case MESSAGE_TYPE_RECEIVER:
- message = cc_comm_build_message(
- comm->sender_id,
- "urn:x-cast:com.google.cast.receiver",
- CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
- NULL,
- utf8_payload);
- break;
-
- case MESSAGE_TYPE_MEDIA:
- message = cc_comm_build_message(
- comm->sender_id,
- "urn:x-cast:com.google.cast.media",
- CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
- NULL,
- utf8_payload);
- message.destination_id = comm->destination_id;
- break;
-
- default:
- return FALSE;
- }
+ break;
+
+ case MESSAGE_TYPE_DISCONNECT:
+ message = cc_comm_build_message (
+ "urn:x-cast:com.google.cast.tp.connection",
+ CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
+ NULL,
+ "{ \"type\": \"CLOSE\" }");
+ break;
- packed_size = castchannel__cast_message__get_packed_size(&message);
- sock_buffer = malloc(4 + packed_size);
+ case MESSAGE_TYPE_PING:
+ message = cc_comm_build_message (
+ "urn:x-cast:com.google.cast.tp.heartbeat",
+ CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
+ NULL,
+ "{ \"type\": \"PING\" }");
+ break;
+
+ case MESSAGE_TYPE_PONG:
+ message = cc_comm_build_message (
+ "urn:x-cast:com.google.cast.tp.heartbeat",
+ CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
+ NULL,
+ "{ \"type\": \"PONG\" }");
+ break;
- guint32 packed_size_be = GUINT32_TO_BE(packed_size);
- memcpy(sock_buffer, &packed_size_be, 4);
- castchannel__cast_message__pack(&message, 4 + sock_buffer);
+ case MESSAGE_TYPE_RECEIVER:
+ message = cc_comm_build_message (
+ "urn:x-cast:com.google.cast.receiver",
+ CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
+ NULL,
+ utf8_payload);
+ break;
+
+ case MESSAGE_TYPE_MEDIA:
+ message = cc_comm_build_message (
+ "urn:x-cast:com.google.cast.media",
+ CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
+ NULL,
+ utf8_payload);
+ message.destination_id = comm->destination_id;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ packed_size = castchannel__cast_message__get_packed_size (&message);
+ sock_buffer = malloc (4 + packed_size);
+
+ guint32 packed_size_be = GUINT32_TO_BE (packed_size);
+
+ memcpy (sock_buffer, &packed_size_be, 4);
+ castchannel__cast_message__pack (&message, 4 + sock_buffer);
if (message_type != MESSAGE_TYPE_PING && message_type != MESSAGE_TYPE_PONG)
- {
- g_debug ("CcComm: Sending message:");
- cc_comm_dump_json_message (&message);
- }
+ {
+ g_debug ("CcComm: Sending message:");
+ cc_comm_dump_json_message (&message);
+ }
return cc_comm_tls_send (comm,
sock_buffer,
- packed_size+4,
+ packed_size + 4,
error);
}
@@ -601,16 +598,16 @@ cc_comm_send_ping (CcComm * comm)
g_autoptr(GError) error = NULL;
// if this errors out, we cancel the periodic ping by returning FALSE
- if (!cc_comm_send_request(comm, MESSAGE_TYPE_PING, NULL, &error))
+ if (!cc_comm_send_request (comm, MESSAGE_TYPE_PING, NULL, &error))
{
if (error != NULL)
{
g_warning ("CcComm: Failed to send ping message: %s", error->message);
- return FALSE;
+ return G_SOURCE_REMOVE;
}
- g_warning ("CcComm: Failed to send ping message");
- return FALSE;
+ g_warning ("CcComm: Failed to send ping message");
+ return G_SOURCE_REMOVE;
}
- return TRUE;
+ return G_SOURCE_CONTINUE;
}
diff --git a/src/cc/cc-comm.h b/src/cc/cc-comm.h
index d958469..fd82b89 100644
--- a/src/cc/cc-comm.h
+++ b/src/cc/cc-comm.h
@@ -28,13 +28,13 @@ G_BEGIN_DECLS
struct _CcComm
{
/*< public >*/
- GIOStream *con;
+ GIOStream *con;
- gchar *sender_id;
- gchar *destination_id;
+ gchar *destination_id;
+ guint8 *header_buffer;
+ guint8 *message_buffer;
- guint8 *header_buffer;
- guint8 *message_buffer;
+ GCancellable *cancellable;
};
typedef struct _CcComm CcComm;
@@ -49,8 +49,13 @@ enum MessageType {
MESSAGE_TYPE_MEDIA,
};
-gboolean cc_comm_make_connection (CcComm *comm, gchar *remote_address, GError **error);
-gboolean cc_comm_send_request (CcComm *sink, enum MessageType message_type, char *utf8_payload, GError
**error);
+gboolean cc_comm_make_connection (CcComm *comm,
+ gchar *remote_address,
+ GError **error);
+gboolean cc_comm_send_request (CcComm *sink,
+ enum MessageType message_type,
+ char *utf8_payload,
+ GError **error);
gboolean cc_comm_send_ping (CcComm *sink);
G_END_DECLS
diff --git a/src/nd-cc-sink.c b/src/nd-cc-sink.c
index 2021b2c..49b7c91 100644
--- a/src/nd-cc-sink.c
+++ b/src/nd-cc-sink.c
@@ -29,25 +29,25 @@
struct _NdCCSink
{
- GObject parent_instance;
+ GObject parent_instance;
- NdSinkState state;
+ NdSinkState state;
- GCancellable *cancellable;
+ GCancellable *cancellable;
- GStrv missing_video_codec;
- GStrv missing_audio_codec;
- char *missing_firewall_zone;
+ GStrv missing_video_codec;
+ GStrv missing_audio_codec;
+ char *missing_firewall_zone;
- gchar *remote_address;
- gchar *remote_name;
+ gchar *remote_address;
+ gchar *remote_name;
- GSocketClient *comm_client;
- CcComm comm;
- guint ping_timeout_handle;
+ GSocketClient *comm_client;
+ CcComm comm;
+ guint ping_timeout_handle;
- WfdServer *server;
- guint server_source_id;
+ WfdServer *server;
+ guint server_source_id;
};
enum {
@@ -81,9 +81,9 @@ G_DEFINE_TYPE_EXTENDED (NdCCSink, nd_cc_sink, G_TYPE_OBJECT, 0,
static GParamSpec * props[PROP_LAST] = { NULL, };
static void
-nd_cc_sink_get_property (GObject * object,
+nd_cc_sink_get_property (GObject * object,
guint prop_id,
- GValue * value,
+ GValue * value,
GParamSpec * pspec)
{
NdCCSink *sink = ND_CC_SINK (object);
@@ -263,7 +263,7 @@ static void
closed_cb (NdCCSink *sink, CCClient *client)
{
/* Connection was closed, do a clean shutdown */
- cc_comm_send_request(&sink->comm, MESSAGE_TYPE_DISCONNECT, NULL, NULL);
+ cc_comm_send_request (&sink->comm, MESSAGE_TYPE_DISCONNECT, NULL, NULL);
nd_cc_sink_sink_stop_stream (ND_SINK (sink));
}
@@ -312,33 +312,19 @@ server_create_audio_source_cb (NdCCSink *sink, WfdServer *server)
return res;
}
-static gboolean
-nd_cc_sink_close_conn_cb (NdCCSink *sink)
-{
- if (!cc_comm_send_request(&sink->comm, MESSAGE_TYPE_DISCONNECT, NULL, NULL))
- {
- g_warning ("NdCCSink: something went wrong with closing connection");
- }
- return FALSE;
-}
-
static gboolean
nd_cc_sink_launch_default_app_cb (NdCCSink *sink)
{
- if (!cc_comm_send_request(&sink->comm, MESSAGE_TYPE_RECEIVER, "{ \"type\": \"LAUNCH\", \"appId\":
\"CC1AD845\", \"requestId\": 3 }", NULL))
- {
+ if (!cc_comm_send_request (&sink->comm, MESSAGE_TYPE_RECEIVER, "{ \"type\": \"LAUNCH\", \"appId\":
\"CC1AD845\", \"requestId\": 3 }", NULL))
g_warning ("NdCCSink: something went wrong with default app launch");
- }
return FALSE;
}
static gboolean
nd_cc_sink_get_status_cb (NdCCSink *sink)
{
- if (!cc_comm_send_request(&sink->comm, MESSAGE_TYPE_RECEIVER, "{ \"type\": \"GET_STATUS\", \"requestId\":
2 }", NULL))
- {
+ if (!cc_comm_send_request (&sink->comm, MESSAGE_TYPE_RECEIVER, "{ \"type\": \"GET_STATUS\", \"requestId\":
2 }", NULL))
g_warning ("NdCCSink: something went wrong with get status");
- }
return FALSE;
}
@@ -346,6 +332,7 @@ static NdSink *
nd_cc_sink_sink_start_stream (NdSink *sink)
{
NdCCSink *self = ND_CC_SINK (sink);
+
g_autoptr(GError) error = NULL;
// gchar six_digits[6];
@@ -361,11 +348,11 @@ nd_cc_sink_sink_start_stream (NdSink *sink)
g_debug ("NdCCSink: Attempting connection to Chromecast: %s", self->remote_name);
- self->comm.sender_id = g_strdup ("sender-gnd");
- self->comm.destination_id = g_strdup ("receiver-0");
+ self->comm.destination_id = "receiver-0";
+ self->comm.cancellable = self->cancellable;
// open a TLS connection to the CC device
- if (!cc_comm_make_connection(&self->comm, self->remote_address, &error))
+ if (!cc_comm_make_connection (&self->comm, self->remote_address, &error))
{
self->state = ND_SINK_STATE_ERROR;
g_object_notify (G_OBJECT (self), "state");
@@ -375,7 +362,7 @@ nd_cc_sink_sink_start_stream (NdSink *sink)
}
// authenticate with the CC device
- if (!cc_comm_send_request(&self->comm, MESSAGE_TYPE_AUTH, NULL, NULL))
+ if (!cc_comm_send_request (&self->comm, MESSAGE_TYPE_AUTH, NULL, NULL))
{
self->state = ND_SINK_STATE_ERROR;
g_object_notify (G_OBJECT (self), "state");
@@ -385,7 +372,7 @@ nd_cc_sink_sink_start_stream (NdSink *sink)
}
// open up a virtual connection to the device
- if (!cc_comm_send_request(&self->comm, MESSAGE_TYPE_CONNECT, NULL, NULL))
+ if (!cc_comm_send_request (&self->comm, MESSAGE_TYPE_CONNECT, NULL, NULL))
{
self->state = ND_SINK_STATE_ERROR;
g_object_notify (G_OBJECT (self), "state");
@@ -394,27 +381,18 @@ nd_cc_sink_sink_start_stream (NdSink *sink)
return NULL;
}
- // sprintf (six_digits, "%ld", time (NULL) % 1000000);
- // self->comm.sender_id = "sender-";
- // strncat (self->comm.sender_id, six_digits, 6);
-
- // set sender_id after connection (sender-xxxxxx)
-
// send pings to device every 5 seconds
- self->ping_timeout_handle = g_timeout_add_seconds(5, G_SOURCE_FUNC (cc_comm_send_ping), &self->comm);
+ self->ping_timeout_handle = g_timeout_add_seconds (5, G_SOURCE_FUNC (cc_comm_send_ping), &self->comm);
// send req to get status
- g_debug("NdCCSink: Get Status");
+ g_debug ("NdCCSink: Get Status");
g_timeout_add_seconds (2, G_SOURCE_FUNC (nd_cc_sink_get_status_cb), self);
- g_debug("NdCCSink: Launching Default Media App");
+ g_debug ("NdCCSink: Launching Default Media App");
g_timeout_add_seconds (6, G_SOURCE_FUNC (nd_cc_sink_launch_default_app_cb), self);
- g_debug("NdCCSink: Closing Connection");
- g_timeout_add_seconds (60, G_SOURCE_FUNC (nd_cc_sink_close_conn_cb), self);
-
- // g_debug ("NdCCSink: Mute the Chromecast");
- // cc_comm_send_request(&self->comm, MESSAGE_TYPE_RECEIVER, "{ \"type\": \"SET_VOLUME\", \"volume\": {
\"muted\": true } }", NULL);
+ self->state = ND_SINK_STATE_STREAMING;
+ g_object_notify (G_OBJECT (self), "state");
self->server = wfd_server_new ();
self->server_source_id = gst_rtsp_server_attach (GST_RTSP_SERVER (self->server), NULL);
@@ -446,8 +424,8 @@ nd_cc_sink_sink_start_stream (NdSink *sink)
self,
G_CONNECT_SWAPPED);
- self->state = ND_SINK_STATE_WAIT_SOCKET;
- g_object_notify (G_OBJECT (self), "state");
+ // self->state = ND_SINK_STATE_WAIT_SOCKET;
+ // g_object_notify (G_OBJECT (self), "state");
// these were originally here
// 1. send connect request
@@ -459,27 +437,53 @@ nd_cc_sink_sink_start_stream (NdSink *sink)
static void
nd_cc_sink_sink_stop_stream_int (NdCCSink *self)
{
- g_autoptr(GError) error;
+ g_autoptr(GError) error = NULL;
gboolean close_ok;
+ // Close the app before closing the connection
+ // hack to know if the app is already up
+ if (g_strcmp0 (self->comm.destination_id, "receiver-0") != 0)
+ {
+ g_autoptr(GString) close_app_message = NULL;
+ close_app_message = g_string_new ("{ \"type\": \"STOP\", \"requestId\": 5, \"sessionId\": \"");
+ g_string_append (close_app_message, self->comm.destination_id);
+ g_string_append (close_app_message, "\" }");
+
+ if (!cc_comm_send_request (&self->comm, MESSAGE_TYPE_RECEIVER, close_app_message->str, &error))
+ {
+ if (error != NULL)
+ g_warning ("NdCCSink: Error closing the cast app: %s", error->message);
+ else
+ g_warning ("NdCCSink: Error closing the cast app");
+ }
+
+ g_clear_error (&error);
+ g_clear_pointer (&self->comm.destination_id, g_free);
+ self->comm.destination_id = g_strdup ("receiver-0");
+ }
+
+ if (!cc_comm_send_request (&self->comm, MESSAGE_TYPE_DISCONNECT, NULL, NULL))
+ g_warning ("NdCCSink: Error closing virtual connection");
+
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
self->cancellable = g_cancellable_new ();
+ // cancel ping timeout
+ g_clear_handle_id (&self->ping_timeout_handle, g_source_remove);
+
/* Close the client connection
- * FIX: this does not close the connection
* TODO: This should be moved into cc-comm.c */
if (self->comm.con != NULL)
{
close_ok = g_io_stream_close (G_IO_STREAM (self->comm.con), NULL, &error);
- if (error != NULL)
- {
- g_warning ("NdCCSink: Error closing communication client connection: %s", error->message);
- }
if (!close_ok)
{
- g_warning ("NdCCSink: Communication client connection not closed");
+ if (error != NULL)
+ g_warning ("NdCCSink: Error closing communication client connection: %s", error->message);
+ else
+ g_warning ("NdCCSink: Communication client connection not closed");
}
g_clear_object (&self->comm.con);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]