summaryrefslogtreecommitdiff
path: root/telepathy-logger/text-channel.c
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@collabora.co.uk>2011-03-15 15:38:10 -0400
committerNicolas Dufresne <nicolas.dufresne@collabora.co.uk>2011-03-15 15:38:10 -0400
commit05d6e6d865253c99f1a59e65130721c3e4598afe (patch)
tree181f95b026f2b4453aa837f3be0746fb524c361f /telepathy-logger/text-channel.c
parentdf2547d5205fff079db04fccf75b553a168aed22 (diff)
downloadtelepathy-logger-05d6e6d865253c99f1a59e65130721c3e4598afe.tar.gz
Port to Message interface
Diffstat (limited to 'telepathy-logger/text-channel.c')
-rw-r--r--telepathy-logger/text-channel.c378
1 files changed, 160 insertions, 218 deletions
diff --git a/telepathy-logger/text-channel.c b/telepathy-logger/text-channel.c
index 6cf9aa3..6b2f054 100644
--- a/telepathy-logger/text-channel.c
+++ b/telepathy-logger/text-channel.c
@@ -56,15 +56,6 @@ struct _TplTextChannelPriv
GHashTable *entities;
};
-typedef struct
-{
- gint msg_id;
- guint type;
- gchar *text;
- gint64 timestamp;
-
-} ReceivedData;
-
static TpContactFeature features[3] = {
TP_CONTACT_FEATURE_ALIAS,
TP_CONTACT_FEATURE_PRESENCE,
@@ -76,17 +67,20 @@ G_DEFINE_TYPE (TplTextChannel, _tpl_text_channel, TPL_TYPE_CHANNEL)
static void
got_tpl_chan_ready_cb (GObject *obj,
- GAsyncResult *tpl_chan_result,
+ GAsyncResult *result,
gpointer user_data)
{
+ TpProxy *proxy = TP_PROXY (obj);
TplActionChain *ctx = user_data;
- /* if TplChannel preparation is OK, keep on with the TplTextChannel */
- if (_tpl_action_chain_new_finish (tpl_chan_result))
+ /* if TplChannel preparation is OK (and support Message interface,
+ * keep on with the TplTextChannel */
+ if (_tpl_action_chain_new_finish (result)
+ && tp_proxy_has_interface_by_id (proxy,
+ TP_IFACE_QUARK_CHANNEL_INTERFACE_MESSAGES))
_tpl_action_chain_continue (ctx);
else
_tpl_action_chain_terminate (ctx);
- return;
}
@@ -300,269 +294,222 @@ on_channel_invalidated_cb (TpProxy *proxy,
static void
-keepon_on_receiving_signal (TplTextChannel *tpl_text,
+tpl_text_channel_store_message (TplTextChannel *self,
+ const GPtrArray *message,
TplEntity *sender,
- ReceivedData *data)
+ TplEntity *receiver)
{
- TplTextEvent *text_log;
- GError *error = NULL;
+ TplTextChannelPriv *priv = self->priv;
+ const gchar *direction;
+ GHashTable *header;
+ TpChannelTextMessageType type;
+ TplEntity *allocated_sender = NULL;
+ gboolean valid;
+ gint64 timestamp;
+ guint i;
+ const gchar *text = NULL;
+ TplTextEvent *event;
TplLogManager *logmanager;
- TplEntity *receiver;
+ GError *error = NULL;
- if (tpl_text->priv->is_chatroom)
- receiver = tpl_text->priv->chatroom;
+ if (sender != NULL
+ && tpl_entity_get_entity_type (sender) == TPL_ENTITY_SELF)
+ direction = "sent";
else
- receiver = tpl_text->priv->self;
+ direction = "received";
- /* Initialize TplTextEvent */
- text_log = g_object_new (TPL_TYPE_TEXT_EVENT,
- /* TplEvent */
- "account", _tpl_channel_get_account (TPL_CHANNEL (tpl_text)),
- "channel-path", tp_proxy_get_object_path (TP_PROXY (tpl_text)),
- "receiver", receiver,
- "sender", sender,
- "timestamp", data->timestamp,
- /* TplTextEvent */
- "message-type", data->type,
- "message", data->text,
- "pending-msg-id", data->msg_id,
- NULL);
-
- DEBUG ("recvd:\n\tto=\"%s (%s)\"\n\tfrom=\"%s (%s)\"\n\tmsg=\"%s\"",
- tpl_entity_get_identifier (receiver),
- tpl_entity_get_alias (receiver),
- tpl_entity_get_identifier (sender),
- tpl_entity_get_alias (sender),
- tpl_text_event_get_message (text_log));
+ header = g_ptr_array_index (message, 0);
- logmanager = tpl_log_manager_dup_singleton ();
- _tpl_log_manager_add_event (logmanager, TPL_EVENT (text_log), &error);
-
- if (error != NULL)
+ if (header == NULL)
{
- DEBUG ("%s", error->message);
- g_error_free (error);
+ DEBUG ("Got invalid or corrupted %s message that could not be logged.",
+ direction);
+ return;
}
- g_object_unref (text_log);
- g_object_unref (logmanager);
-}
-
-
-static void
-on_received_signal_with_contact_cb (TpConnection *connection,
- guint n_contacts,
- TpContact *const *contacts,
- guint n_failed,
- const TpHandle *failed,
- const GError *error,
- gpointer user_data,
- GObject *weak_object)
-{
- ReceivedData *data = user_data;
- TplTextChannel *tpl_text = TPL_TEXT_CHANNEL (weak_object);
- TplEntity *remote;
- TpHandle handle;
+ if (tp_asv_get_boolean (header, "scrollback", NULL))
+ {
+ DEBUG ("Ignoring %s scrollback message.", direction);
+ return;
+ }
- if (error != NULL)
+ if (tp_asv_get_boolean (header, "rescued", NULL))
{
- PATH_DEBUG (tpl_text, "An Unrecoverable error retrieving remote contact "
- "information occured: %s", error->message);
- PATH_DEBUG (tpl_text, "Unable to log the received message: %s",
- data->text);
+ DEBUG ("Ignoring %s rescued message.", direction);
return;
}
- if (n_failed > 0)
+ type = tp_asv_get_uint32 (header, "message-type", NULL);
+
+ if (type == TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT)
{
- PATH_DEBUG (tpl_text, "%d invalid handle(s) passed to "
- "tp_connection_get_contacts_by_handle()", n_failed);
- PATH_DEBUG (tpl_text, "Not able to log the received message: %s",
- data->text);
+ DEBUG ("Ignoring %s delivery report message.", direction);
return;
}
- remote = tpl_entity_new_from_tp_contact (contacts[0], TPL_ENTITY_CONTACT);
- handle = tp_contact_get_handle (contacts[0]);
+ /* Need to determin sender for incoming messages */
+ if (sender == NULL)
+ {
+ TpHandle handle;
- g_hash_table_insert (tpl_text->priv->entities, GUINT_TO_POINTER (handle),
- remote);
+ handle = tp_asv_get_uint32 (header, "message-sender", NULL);
- keepon_on_receiving_signal (tpl_text, remote, data);
-}
+ /* For non-chatroom, message handle is also the channel handle */
+ if (handle == 0 && !priv->is_chatroom)
+ handle = tp_channel_get_handle (TP_CHANNEL (self), NULL);
+ if (handle != 0)
+ sender = g_hash_table_lookup (priv->entities,
+ GUINT_TO_POINTER (handle));
-static void
-received_data_free (gpointer arg)
-{
- ReceivedData *data = arg;
- g_free (data->text);
- g_slice_free (ReceivedData,data);
-}
+ /* If it's a chatroom and sender is not member rely on message header to
+ * get the appropriate sender information */
+ if (sender == NULL && priv->is_chatroom)
+ {
+ const gchar *id;
+ const gchar *alias;
+ id = tp_asv_get_string (header, "message-sender-id");
+ alias = tp_asv_get_string (header, "sender-nickname");
-static void
-on_received_signal_cb (TpChannel *proxy,
- guint msg_id,
- guint timestamp,
- TpHandle sender,
- guint type,
- guint flags,
- const gchar *text,
- gpointer user_data,
- GObject *weak_object)
-{
- TplTextChannel *tpl_text = TPL_TEXT_CHANNEL (proxy);
- TpConnection *tp_conn;
- TplEntity *remote;
- ReceivedData *data;
-
- /* TODO use the Message iface to check the delivery
- notification and handle it correctly */
- if (flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_NON_TEXT_CONTENT)
- {
- PATH_DEBUG (tpl_text, "Non text content flag set. "
- "Probably a delivery notification for a sent message. "
- "Ignoring");
- return;
+ if (id != NULL)
+ allocated_sender = sender =
+ tpl_entity_new (id, TPL_ENTITY_CONTACT, alias, NULL);
+ }
+
+ /* If we still don't have a sender, then make it unknown */
+ if (sender == NULL)
+ allocated_sender = sender =
+ tpl_entity_new ("unknown", TPL_ENTITY_UNKNOWN, NULL, NULL);
}
- if (flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_RESCUED)
+ /* Sender nickname may change for each messages */
+ if (!TPL_STR_EMPTY (tp_asv_get_string (header, "sender-nickname"))
+ && (allocated_sender == NULL))
{
- PATH_DEBUG (tpl_text, "Ignore 'rescued' message");
- return;
+ if (g_strcmp0 (tpl_entity_get_alias (sender),
+ tp_asv_get_string (header, "sender-nickname")) != 0)
+ allocated_sender = sender =
+ tpl_entity_new (tpl_entity_get_identifier (sender),
+ tpl_entity_get_entity_type (sender),
+ tp_asv_get_string (header, "sender-nickname"),
+ tpl_entity_get_avatar_token (sender));
}
- data = g_slice_new0 (ReceivedData);
- data->msg_id = msg_id;
- data->type = type;
- data->text = g_strdup (text);
- data->timestamp = timestamp;
+ /* Ensure timestamp */
+ timestamp = tp_asv_get_int64 (header, "message-sent", &valid);
- tp_conn = tp_channel_borrow_connection (TP_CHANNEL (tpl_text));
- remote = g_hash_table_lookup (tpl_text->priv->entities,
- GUINT_TO_POINTER (sender));
+ if (!valid)
+ timestamp = tp_asv_get_int64 (header, "message-received", &valid);
- if (remote == NULL)
+ if (!valid)
{
- /* Contact is not in the cache */
- tp_connection_get_contacts_by_handle (tp_conn, 1, &sender,
- G_N_ELEMENTS (features), features, on_received_signal_with_contact_cb,
- data, received_data_free, G_OBJECT (tpl_text));
+ GDateTime *datetime = g_date_time_new_now_utc ();
+ timestamp = g_date_time_to_unix (datetime);
+ g_date_time_unref (datetime);
}
- else
- {
- keepon_on_receiving_signal (tpl_text, remote, data);
- received_data_free (data);
- }
-}
-
-
-static void
-on_sent_signal_cb (TpChannel *proxy,
- guint tp_timestamp,
- guint type,
- const gchar *text,
- gpointer user_data,
- GObject *weak_object)
-{
- GError *error = NULL;
- TplTextChannel *tpl_text = TPL_TEXT_CHANNEL (user_data);
- TplEntity *sender;
- TplEntity *receiver = NULL;
- TplTextEvent *text_log;
- TplLogManager *logmanager;
- TpAccount *account;
- const gchar *channel_path;
- gint64 timestamp = (gint64) tp_timestamp;
- g_return_if_fail (TPL_IS_TEXT_CHANNEL (tpl_text));
+ for (i = 1; (i < message->len) && (text == NULL); i++)
+ {
+ GHashTable *part = g_ptr_array_index (message, i);
- channel_path = tp_proxy_get_object_path (TP_PROXY (tpl_text));
+ if (tp_strdiff ("text/plain",
+ tp_asv_get_string (part, "content-type")))
+ {
+ DEBUG ("Non text/plain content ignored, content of type = '%s'",
+ tp_asv_get_string (part, "content-type"));
+ continue;
+ }
- /* Initialize data for TplEntity */
- sender = tpl_text->priv->self;
+ text = tp_asv_get_string (part, "content");
+ }
- if (tpl_text->priv->is_chatroom)
+ if (text == NULL)
{
- receiver = tpl_text->priv->chatroom;
-
- DEBUG ("sent:\n\tto chatroom=\"%s\"\n\tfrom=\"%s (%s)\"\n\tmsg=\"%s\"",
- tpl_entity_get_identifier (receiver),
- tpl_entity_get_identifier (sender),
- tpl_entity_get_alias (sender),
- text);
+ DEBUG ("Ignoring %s message with no supported content", direction);
+ tp_clear_object (&allocated_sender);
+ return;
}
- else
- {
- TpHandle handle = tp_channel_get_handle (TP_CHANNEL (tpl_text), NULL);
-
- receiver = g_hash_table_lookup (tpl_text->priv->entities,
- GUINT_TO_POINTER (handle));
- /* FIXME Create unkown entity when supported, this way we can survive
- * buggy connection managers */
- g_assert (receiver != NULL);
+ if (tpl_entity_get_entity_type (sender) == TPL_ENTITY_SELF)
+ DEBUG ("Logging message sent to %s (%s)",
+ tpl_entity_get_alias (receiver),
+ tpl_entity_get_identifier (receiver));
+ else
+ DEBUG ("Logging message received from %s (%s)",
+ tpl_entity_get_alias (sender),
+ tpl_entity_get_identifier (sender));
- DEBUG ("sent:\n\tto=\"%s (%s)\"\n\tfrom=\"%s (%s)\"\n\tmsg=\"%s\"",
- tpl_entity_get_identifier (receiver),
- tpl_entity_get_alias (receiver),
- tpl_entity_get_identifier (sender),
- tpl_entity_get_alias (sender),
- text);
- }
/* Initialise TplTextEvent */
- account = _tpl_channel_get_account (TPL_CHANNEL (tpl_text));
- text_log = g_object_new (TPL_TYPE_TEXT_EVENT,
+ event = g_object_new (TPL_TYPE_TEXT_EVENT,
/* TplEvent */
- "account", account,
- "channel-path", channel_path,
+ "account", _tpl_channel_get_account (TPL_CHANNEL (self)),
+ "channel-path", tp_proxy_get_object_path (TP_PROXY (self)),
"receiver", receiver,
"sender", sender,
"timestamp", timestamp,
/* TplTextEvent */
"message-type", type,
"message", text,
- "pending-msg-id", TPL_TEXT_EVENT_MSG_ID_ACKNOWLEDGED,
NULL);
+ /* Store sent event */
logmanager = tpl_log_manager_dup_singleton ();
- _tpl_log_manager_add_event (logmanager, TPL_EVENT (text_log), &error);
+ _tpl_log_manager_add_event (logmanager, TPL_EVENT (event), &error);
if (error != NULL)
{
- PATH_DEBUG (tpl_text, "LogStore: %s", error->message);
+ PATH_DEBUG (self, "LogStore: %s", error->message);
g_error_free (error);
}
g_object_unref (logmanager);
- g_object_unref (text_log);
+ g_object_unref (event);
+ tp_clear_object (&allocated_sender);
}
static void
-on_send_error_cb (TpChannel *proxy,
- guint error,
- guint timestamp,
- guint type,
- const gchar *text,
- gpointer user_data,
- GObject *weak_object)
+on_message_received_cb (TpChannel *proxy,
+ const GPtrArray *message,
+ gpointer user_data,
+ GObject *weak_object)
{
- PATH_DEBUG (proxy, "unlogged event: TP was unable to send the message: %s",
- text);
- /* TODO log that the system was unable to send the message */
+ TplTextChannel *self = TPL_TEXT_CHANNEL (proxy);
+ TplTextChannelPriv *priv = self->priv;
+ TplEntity *receiver;
+
+ if (priv->is_chatroom)
+ receiver = priv->chatroom;
+ else
+ receiver = priv->self;
+
+ tpl_text_channel_store_message (self, message, NULL, receiver);
}
static void
-on_lost_message_cb (TpChannel *proxy,
- gpointer user_data,
- GObject *weak_object)
+on_message_sent_cb (TpChannel *proxy,
+ const GPtrArray *message,
+ guint flags,
+ const gchar *token,
+ gpointer user_data,
+ GObject *weak_object)
{
- PATH_DEBUG (proxy, "lost message signal catched. nothing logged");
- /* TODO log that the system lost a message */
+ TplTextChannel *self = TPL_TEXT_CHANNEL (proxy);
+ TplTextChannelPriv *priv = self->priv;
+ TpChannel *chan = TP_CHANNEL (self);
+ TplEntity *sender = priv->self;
+ TplEntity *receiver;
+
+ if (priv->is_chatroom)
+ receiver = priv->chatroom;
+ else
+ receiver = g_hash_table_lookup (priv->entities,
+ GUINT_TO_POINTER (tp_channel_get_handle (chan, NULL)));
+
+ tpl_text_channel_store_message (self, message, sender, receiver);
}
@@ -577,20 +524,14 @@ pendingproc_connect_message_signals (TplActionChain *ctx,
tp_g_signal_connect_object (channel, "invalidated",
G_CALLBACK (on_channel_invalidated_cb), tpl_text, 0);
- if (tp_cli_channel_type_text_connect_to_received (channel,
- on_received_signal_cb, NULL, NULL, NULL, &error) == NULL)
- goto disaster;
-
- if (tp_cli_channel_type_text_connect_to_sent (channel,
- on_sent_signal_cb, tpl_text, NULL, NULL, &error) == NULL)
+ if (tp_cli_channel_interface_messages_connect_to_message_received (
+ channel, on_message_received_cb, NULL, NULL,
+ G_OBJECT (tpl_text), &error) == NULL)
goto disaster;
- if (tp_cli_channel_type_text_connect_to_send_error (channel,
- on_send_error_cb, tpl_text, NULL, NULL, &error) == NULL)
- goto disaster;
-
- if (tp_cli_channel_type_text_connect_to_lost_message (channel,
- on_lost_message_cb, tpl_text, NULL, NULL, &error) == NULL)
+ if (tp_cli_channel_interface_messages_connect_to_message_sent (
+ channel, on_message_sent_cb, NULL, NULL,
+ G_OBJECT (tpl_text), &error) == NULL)
goto disaster;
_tpl_action_chain_continue (ctx);
@@ -612,7 +553,7 @@ tpl_text_channel_call_when_ready (TplChannel *chan,
/* first: connect signals, so none are lost
* second: prepare all TplChannel
* third: cache my contact and the remote one.
- * last: connect message signals
+ * last: connect to Message signals
*
* If for any reason, the order is changed, it's needed to check what objects
* are unreferenced by g_object_unref but used by a next action AND what
@@ -622,6 +563,7 @@ tpl_text_channel_call_when_ready (TplChannel *chan,
_tpl_action_chain_append (actions, pendingproc_get_my_contact, NULL);
_tpl_action_chain_append (actions, pendingproc_get_remote_contacts, NULL);
_tpl_action_chain_append (actions, pendingproc_connect_message_signals, NULL);
+
/* start the chain consuming */
_tpl_action_chain_continue (actions);
}