[gnome-network-displays/cc-tmp: 17/80] cc: added auth message and json parser for received messages




commit 495c50d6c40050e733390c1dcb50ec317e5adff1
Author: Anupam Kumar <kyteinsky gmail com>
Date:   Thu Jul 28 23:02:16 2022 +0530

    cc: added auth message and json parser for received messages

 src/cc/cc-comm.c   | 124 +++++++++++++++++++++++++++++++++++++++++++++++++----
 src/cc/cc-comm.h   |   4 ++
 src/cc/meson.build |   1 +
 src/nd-cc-sink.c   |  54 +++++++++++++++++++----
 4 files changed, 166 insertions(+), 17 deletions(-)
---
diff --git a/src/cc/cc-comm.c b/src/cc/cc-comm.c
index 8088e28..426a16f 100644
--- a/src/cc/cc-comm.c
+++ b/src/cc/cc-comm.c
@@ -26,6 +26,19 @@ static void cc_comm_listen (CcComm *comm);
 static void cc_comm_read (CcComm *comm, gsize io_bytes, gboolean read_header);
 
 
+static void
+cc_comm_load_media (CcComm *comm)
+{
+  gboolean send_ok = 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);
+
+  if (!send_ok)
+  {
+    g_warning ("NdCCSink: something went wrong with load media");
+  }
+
+  g_clear_pointer (&comm->destination_id, g_free);
+}
+
 static void
 cc_comm_dump_message (guint8 *msg, gsize length)
 {
@@ -58,8 +71,61 @@ cc_comm_dump_json_message (Castchannel__CastMessage *message)
            message->payload_utf8);
 }
 
+// returns FALSE if message is PONG
+// returns TRUE if the message is to be logged
+static gboolean
+cc_comm_parse_json_data (CcComm *comm, char *payload)
+{
+  g_autoptr(GError) error = NULL;
+  g_autoptr(JsonParser) parser;
+  g_autoptr(JsonReader) reader;
+
+  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;
+  }
+
+  reader = json_reader_new (json_parser_get_root (parser));
+
+  json_reader_read_member (reader, "type");
+  const char *message_type = json_reader_get_string_value (reader);
+  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)
+            {
+              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);
+              comm->destination_id = g_strdup (transport_id);
+              cc_comm_load_media (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(uint8_t * input_buffer, gssize input_size)
+cc_comm_parse_received_data(CcComm *comm, uint8_t * input_buffer, gssize input_size)
 {
   Castchannel__CastMessage *message;
 
@@ -70,8 +136,11 @@ cc_comm_parse_received_data(uint8_t * input_buffer, gssize input_size)
     return;
   }
 
-  g_debug("CcComm: Received data:");
-  cc_comm_dump_json_message (message);
+  if (cc_comm_parse_json_data (comm, message->payload_utf8))
+  {
+    g_debug("CcComm: Received data:");
+    cc_comm_dump_json_message (message);
+  }
 
   castchannel__cast_message__free_unpacked(message, NULL);
 }
@@ -156,7 +225,9 @@ cc_comm_message_read_cb (GObject *source_object,
 
   // dump the received message and try to parse it
   // cc_comm_dump_message (comm->message_buffer, io_bytes);
-  cc_comm_parse_received_data (comm->message_buffer, io_bytes);
+  cc_comm_parse_received_data (comm, comm->message_buffer, io_bytes);
+
+  g_clear_pointer (&comm->message_buffer, g_free);
 
   // go for another round
   cc_comm_listen(comm);
@@ -213,6 +284,8 @@ cc_comm_header_read_cb (GObject *source_object,
   message_size = cc_comm_to_message_size (comm);
   g_debug ("CcComm: Message size: %d", message_size);
 
+  g_clear_pointer (&comm->header_buffer, g_free);
+
   comm->message_buffer = g_malloc0 (message_size);
   cc_comm_read (comm, message_size, FALSE);
 }
@@ -380,7 +453,8 @@ cc_comm_tls_send (CcComm        * comm,
 
 // builds message based on available types
 static Castchannel__CastMessage
-cc_comm_build_message (gchar *namespace_,
+cc_comm_build_message (gchar *source_id,
+                       gchar *namespace_,
                        Castchannel__CastMessage__PayloadType payload_type,
                        ProtobufCBinaryData * binary_payload,
                        gchar *utf8_payload)
@@ -389,7 +463,7 @@ cc_comm_build_message (gchar *namespace_,
   castchannel__cast_message__init(&message);
 
   message.protocol_version = CASTCHANNEL__CAST_MESSAGE__PROTOCOL_VERSION__CASTV2_1_0;
-  message.source_id = "sender-0";
+  message.source_id = source_id;
   message.destination_id = "receiver-0";
   message.namespace_ = namespace_;
   message.payload_type = payload_type;
@@ -419,16 +493,32 @@ cc_comm_send_request (CcComm * comm, enum MessageType message_type, char *utf8_p
 
   switch (message_type)
   {
+  case MESSAGE_TYPE_AUTH:
+    ProtobufCBinaryData binary_payload;
+    binary_payload.data = NULL;
+    binary_payload.len = 0;
+
+    message = cc_comm_build_message(
+      "sender-0",
+      "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(
+      "sender-0",
       "urn:x-cast:com.google.cast.tp.connection",
       CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
       NULL,
-      "{ \"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 } }");
+      "{ \"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 } }");
     break;
 
   case MESSAGE_TYPE_DISCONNECT:
     message = cc_comm_build_message(
+      "sender-0",
       "urn:x-cast:com.google.cast.tp.connection",
       CASTCHANNEL__CAST_MESSAGE__PAYLOAD_TYPE__STRING,
       NULL,
@@ -437,6 +527,7 @@ cc_comm_send_request (CcComm * comm, enum MessageType message_type, char *utf8_p
 
   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,
@@ -445,6 +536,7 @@ cc_comm_send_request (CcComm * comm, enum MessageType message_type, char *utf8_p
 
   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,
@@ -453,12 +545,23 @@ cc_comm_send_request (CcComm * comm, enum MessageType message_type, char *utf8_p
 
   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;
   }
@@ -470,8 +573,11 @@ cc_comm_send_request (CcComm * comm, enum MessageType message_type, char *utf8_p
   memcpy(sock_buffer, &packed_size_be, 4);
   castchannel__cast_message__pack(&message, 4 + sock_buffer);
 
-  g_debug ("CcComm: Sending message:");
-  cc_comm_dump_json_message (&message);
+  if (message_type != MESSAGE_TYPE_PING && message_type != MESSAGE_TYPE_PONG)
+  {
+    g_debug ("CcComm: Sending message:");
+    cc_comm_dump_json_message (&message);
+  }
 
   return cc_comm_tls_send (comm,
                            sock_buffer,
diff --git a/src/cc/cc-comm.h b/src/cc/cc-comm.h
index f511d68..d958469 100644
--- a/src/cc/cc-comm.h
+++ b/src/cc/cc-comm.h
@@ -19,6 +19,7 @@
 #pragma once
 
 #include <gio/gio.h>
+#include <json-glib-1.0/json-glib/json-glib.h>
 
 G_BEGIN_DECLS
 
@@ -30,6 +31,7 @@ struct _CcComm
   GIOStream *con;
 
   gchar     *sender_id;
+  gchar     *destination_id;
 
   guint8    *header_buffer;
   guint8    *message_buffer;
@@ -38,11 +40,13 @@ struct _CcComm
 typedef struct _CcComm CcComm;
 
 enum MessageType {
+  MESSAGE_TYPE_AUTH,
   MESSAGE_TYPE_CONNECT,
   MESSAGE_TYPE_DISCONNECT,
   MESSAGE_TYPE_PING,
   MESSAGE_TYPE_PONG,
   MESSAGE_TYPE_RECEIVER,
+  MESSAGE_TYPE_MEDIA,
 };
 
 gboolean cc_comm_make_connection (CcComm *comm, gchar *remote_address, GError **error);
diff --git a/src/cc/meson.build b/src/cc/meson.build
index 25af912..cbf8275 100644
--- a/src/cc/meson.build
+++ b/src/cc/meson.build
@@ -16,6 +16,7 @@ cc_deps = [
   dependency('gstreamer-video-1.0', version: '>= 1.14'),
   dependency('gstreamer-rtsp-1.0', version: '>= 1.14'),
   dependency('libprotobuf-c', version: '>= 1.0.0'),
+  dependency('json-glib-1.0', version: '>= 1.0'),
 ]
 
 cc_cast_channel = static_library(
diff --git a/src/nd-cc-sink.c b/src/nd-cc-sink.c
index 05dfc13..cce8dc2 100644
--- a/src/nd-cc-sink.c
+++ b/src/nd-cc-sink.c
@@ -312,6 +312,36 @@ 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))
+  {
+    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))
+  {
+    g_warning ("NdCCSink: something went wrong with get status");
+  }
+  return FALSE;
+}
+
 static NdSink *
 nd_cc_sink_sink_start_stream (NdSink *sink)
 {
@@ -341,6 +371,16 @@ nd_cc_sink_sink_start_stream (NdSink *sink)
       return NULL;
     }
 
+  // authenticate with the CC device
+  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");
+      g_clear_object (&self->server);
+
+      return NULL;
+    }
+
   // open up a virtual connection to the device
   if (!cc_comm_send_request(&self->comm, MESSAGE_TYPE_CONNECT, NULL, NULL))
     {
@@ -356,22 +396,20 @@ nd_cc_sink_sink_start_stream (NdSink *sink)
   // strncat (self->comm.sender_id, six_digits, 6);
 
   // set sender_id after connection (sender-xxxxxx)
-  self->comm.sender_id = "sender-547784";
+  self->comm.sender_id = "sender-0";
 
   // 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);
-  cc_comm_send_ping (&self->comm);
 
   // send req to get status
   g_debug("NdCCSink: Get Status");
-  cc_comm_send_request(&self->comm, MESSAGE_TYPE_RECEIVER, "{\"type\": \"GET_STATUS\"}", NULL);
+  g_timeout_add_seconds (2, G_SOURCE_FUNC (nd_cc_sink_get_status_cb), self);
 
-  // send req to open youtube
-  // g_debug("NdCCSink: Launching YouTube");
-  // cc_comm_send_request(&self->comm, MESSAGE_TYPE_RECEIVER, "{ \"type\": \"LAUNCH\", \"appId\": 
\"YouTube\", \"requestId\": 1 }", NULL);
+  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: Get Status Again");
-  // cc_comm_send_request(&self->comm, MESSAGE_TYPE_RECEIVER, "{\"type\": \"GET_STATUS\"}", NULL);
+  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);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]