summaryrefslogtreecommitdiff
path: root/telepathy-logger/text-channel.c
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@collabora.co.uk>2011-03-10 16:00:00 -0500
committerNicolas Dufresne <nicolas.dufresne@collabora.co.uk>2011-03-10 16:00:00 -0500
commit438db155a434d8d2584dc739882f1919be1ea325 (patch)
treec374b2ae1488ef754e16228e22e586811c18fe2e /telepathy-logger/text-channel.c
parent1c8dc3eaab53acc935f965aed51d4a4f4f0c991c (diff)
downloadtelepathy-logger-438db155a434d8d2584dc739882f1919be1ea325.tar.gz
Properly reorder methods removing useless wrapper
Diffstat (limited to 'telepathy-logger/text-channel.c')
-rw-r--r--telepathy-logger/text-channel.c1206
1 files changed, 551 insertions, 655 deletions
diff --git a/telepathy-logger/text-channel.c b/telepathy-logger/text-channel.c
index 0c02562..4dabf41 100644
--- a/telepathy-logger/text-channel.c
+++ b/telepathy-logger/text-channel.c
@@ -72,62 +72,36 @@ static TpContactFeature features[3] = {
TP_CONTACT_FEATURE_AVATAR_TOKEN
};
-static void call_when_ready_wrapper (TplChannel *tpl_chan,
- GAsyncReadyCallback cb, gpointer user_data);
-
-static void got_tpl_chan_ready_cb (GObject *obj, GAsyncResult *result,
- gpointer user_data);
-static void on_channel_invalidated_cb (TpProxy *proxy, guint domain, gint code,
- gchar *message, gpointer user_data);
-static void on_lost_message_cb (TpChannel *proxy, gpointer user_data,
- GObject *weak_object);
-static void on_received_signal_cb (TpChannel *proxy, guint msg_id,
- guint timestamp, guint arg_Sender, guint type, guint flags,
- const gchar *text, gpointer user_data, GObject *weak_object);
-static void on_sent_signal_cb (TpChannel *proxy, guint timestamp,
- guint type, const gchar *text, gpointer user_data,
- GObject *weak_object);
-static void on_send_error_cb (TpChannel *proxy, guint arg_Error,
- guint timestamp, guint type, const gchar *text,
- gpointer user_data, GObject *weak_object);
-static void on_pending_messages_removed_cb (TpChannel *proxy,
- const GArray *arg_Message_IDs, gpointer user_data, GObject *weak_object);
-
-static void pendingproc_connect_message_signals (TplActionChain *ctx,
- gpointer user_data);
-static void pendingproc_get_pending_messages (TplActionChain *ctx,
- gpointer user_data);
-static void pendingproc_prepare_tpl_channel (TplActionChain *ctx,
- gpointer user_data);
-#if 0
-static void pendingproc_cleanup_pending_messages_db (TplActionChain *ctx,
- gpointer user_data);
-#endif
+G_DEFINE_TYPE (TplTextChannel, _tpl_text_channel, TPL_TYPE_CHANNEL)
-static void keepon_on_receiving_signal (TplTextChannel *tpl_text,
- TpContact *remote,
- ReceivedData *data);
-static void got_message_pending_messages_cb (TpProxy *proxy,
- const GValue *out_Value, const GError *error, gpointer user_data,
- GObject *weak_object);
-static void got_text_pending_messages_cb (TpChannel *proxy,
- const GPtrArray *result, const GError *error, gpointer user_data,
- GObject *weak_object);
+static void
+got_tpl_chan_ready_cb (GObject *obj,
+ GAsyncResult *tpl_chan_result,
+ gpointer user_data)
+{
+ TplActionChain *ctx = user_data;
+
+ /* if TplChannel preparation is OK, keep on with the TplTextChannel */
+ if (_tpl_action_chain_new_finish (tpl_chan_result))
+ _tpl_action_chain_continue (ctx);
+ else
+ _tpl_action_chain_terminate (ctx);
+ return;
+}
-G_DEFINE_TYPE (TplTextChannel, _tpl_text_channel, TPL_TYPE_CHANNEL)
static void
-_tpl_text_channel_set_my_contact (TplTextChannel *self,
- TpContact *data)
+pendingproc_prepare_tpl_channel (TplActionChain *ctx,
+ gpointer user_data)
{
- g_return_if_fail (TPL_IS_TEXT_CHANNEL (self));
- g_return_if_fail (TP_IS_CONTACT (data));
- g_return_if_fail (self->priv->my_contact == NULL);
+ TplChannel *tpl_chan = TPL_CHANNEL (_tpl_action_chain_get_object (ctx));
- self->priv->my_contact = g_object_ref (data);
+ TPL_CHANNEL_GET_CLASS (tpl_chan)->call_when_ready_protected (tpl_chan,
+ got_tpl_chan_ready_cb, ctx);
}
+
static void
get_self_contact_cb (TpConnection *connection,
guint n_contacts,
@@ -159,11 +133,12 @@ get_self_contact_cb (TpConnection *connection,
return;
}
- _tpl_text_channel_set_my_contact (tpl_text, contacts[0]);
+ tpl_text->priv->my_contact = g_object_ref (contacts[0]);
_tpl_action_chain_continue (ctx);
}
+
static void
pendingproc_get_my_contact (TplActionChain *ctx,
gpointer user_data)
@@ -182,6 +157,7 @@ pendingproc_get_my_contact (TplActionChain *ctx,
G_OBJECT (tpl_text));
}
+
static void
get_remote_contacts_cb (TpConnection *connection,
guint n_contacts,
@@ -218,6 +194,7 @@ get_remote_contacts_cb (TpConnection *connection,
_tpl_action_chain_continue (ctx);
}
+
static void
chan_members_changed_cb (TpChannel *chan,
gchar *message,
@@ -248,6 +225,7 @@ chan_members_changed_cb (TpChannel *chan,
}
}
+
static void
pendingproc_get_remote_contacts (TplActionChain *ctx,
gpointer user_data)
@@ -288,24 +266,6 @@ pendingproc_get_remote_contacts (TplActionChain *ctx,
g_array_free (arr, TRUE);
}
-static void
-_tpl_text_channel_set_chatroom_id (TplTextChannel *self,
- const gchar *data)
-{
- g_return_if_fail (TPL_IS_TEXT_CHANNEL (self));
- g_return_if_fail (!TPL_STR_EMPTY (data));
- g_return_if_fail (self->priv->chatroom_id == NULL);
- self->priv->chatroom_id = g_strdup (data);
-}
-
-static void
-_tpl_text_channel_set_chatroom (TplTextChannel *self,
- gboolean data)
-{
- g_return_if_fail (TPL_IS_TEXT_CHANNEL (self));
-
- self->priv->chatroom = data;
-}
static void
pendingproc_get_room_info (TplActionChain *ctx,
@@ -319,218 +279,429 @@ pendingproc_get_room_info (TplActionChain *ctx,
if (handle_type != TP_HANDLE_TYPE_ROOM)
goto out;
- _tpl_text_channel_set_chatroom (tpl_text, TRUE);
+ tpl_text->priv->chatroom = TRUE;
+ tpl_text->priv->chatroom_id =
+ g_strdup (tp_channel_get_identifier (chan));
- PATH_DEBUG (tpl_text, "Chatroom id: %s", tp_channel_get_identifier (chan));
- _tpl_text_channel_set_chatroom_id (tpl_text,
- tp_channel_get_identifier (chan));
+ PATH_DEBUG (tpl_text, "Chatroom id: %s", tpl_text->priv->chatroom_id);
out:
_tpl_action_chain_continue (ctx);
}
+
static void
-tpl_text_channel_dispose (GObject *obj)
+on_channel_invalidated_cb (TpProxy *proxy,
+ guint domain,
+ gint code,
+ gchar *message,
+ gpointer user_data)
{
- TplTextChannelPriv *priv = TPL_TEXT_CHANNEL (obj)->priv;
+ TplChannel *tpl_chan = TPL_CHANNEL (user_data);
+ TplObserver *observer = _tpl_observer_new ();
- if (priv->my_contact != NULL)
- {
- g_object_unref (priv->my_contact);
- priv->my_contact = NULL;
- }
+ PATH_DEBUG (tpl_chan, "%s #%d %s",
+ g_quark_to_string (domain), code, message);
- tp_clear_pointer (&priv->contacts, g_hash_table_unref);
+ if (!_tpl_observer_unregister_channel (observer, tpl_chan))
+ PATH_DEBUG (tpl_chan, "Channel couldn't be unregistered correctly (BUG?)");
- G_OBJECT_CLASS (_tpl_text_channel_parent_class)->dispose (obj);
+ g_object_unref (observer);
}
static void
-tpl_text_channel_finalize (GObject *obj)
+keepon_on_receiving_signal (TplTextChannel *tpl_text,
+ TpContact *remote,
+ ReceivedData *data)
{
- TplTextChannelPriv *priv = TPL_TEXT_CHANNEL (obj)->priv;
+ TplTextEvent *text_log;
+ GError *error = NULL;
+ TplLogManager *logmanager;
+ TplEntity *sender;
+ TplEntity *receiver;
- PATH_DEBUG (obj, "finalizing channel %p", obj);
+ sender = tpl_entity_new_from_tp_contact (remote, TPL_ENTITY_CONTACT);
- g_free (priv->chatroom_id);
- priv->chatroom_id = NULL;
+ if (tpl_text->priv->chatroom)
+ receiver = tpl_entity_new_from_room_id (tpl_text->priv->chatroom_id);
+ else
+ receiver = tpl_entity_new_from_tp_contact (tpl_text->priv->my_contact,
+ TPL_ENTITY_SELF);
- G_OBJECT_CLASS (_tpl_text_channel_parent_class)->finalize (obj);
+ /* 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)),
+ "log-id", data->log_id,
+ "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\tlog_id=\"%s\"\n\tto=\"%s "
+ "(%s)\"\n\tfrom=\"%s (%s)\"\n\tmsg=\"%s\"",
+ _tpl_event_get_log_id (TPL_EVENT (text_log)),
+ 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));
+
+ logmanager = tpl_log_manager_dup_singleton ();
+ _tpl_log_manager_add_event (logmanager, TPL_EVENT (text_log), &error);
+
+ if (error != NULL)
+ {
+ DEBUG ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (sender);
+ g_object_unref (receiver);
+ g_object_unref (text_log);
+ g_object_unref (logmanager);
}
static void
-_tpl_text_channel_class_init (TplTextChannelClass *klass)
+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)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- TplChannelClass *tpl_chan_class = TPL_CHANNEL_CLASS (klass);
+ ReceivedData *data = user_data;
+ TplTextChannel *tpl_text = TPL_TEXT_CHANNEL (weak_object);
+ TpContact *remote;
+ TpHandle handle;
- object_class->dispose = tpl_text_channel_dispose;
- object_class->finalize = tpl_text_channel_finalize;
+ if (error != 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);
+ return;
+ }
+
+ if (n_failed > 0)
+ {
+ 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);
+ return;
+ }
+
+ remote = contacts[0];
+ handle = tp_contact_get_handle (remote);
- tpl_chan_class->call_when_ready = call_when_ready_wrapper;
+ g_hash_table_insert (tpl_text->priv->contacts, GUINT_TO_POINTER (handle),
+ g_object_ref (remote));
- g_type_class_add_private (object_class, sizeof (TplTextChannelPriv));
+ keepon_on_receiving_signal (tpl_text, remote, data);
}
static void
-_tpl_text_channel_init (TplTextChannel *self)
+received_data_free (gpointer arg)
{
- TplTextChannelPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- TPL_TYPE_TEXT_CHANNEL, TplTextChannelPriv);
+ ReceivedData *data = arg;
+ g_free (data->log_id);
+ g_free (data->text);
+ g_slice_free (ReceivedData,data);
+}
- self->priv = priv;
- self->priv->contacts = g_hash_table_new_full (NULL, NULL, NULL,
- (GDestroyNotify) g_object_unref);
+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;
+ TpContact *remote;
+ TplLogStore *index = _tpl_log_store_sqlite_dup ();
+ const gchar *channel_path = tp_proxy_get_object_path (TP_PROXY (tpl_text));
+ gchar *log_id;
+ 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 (flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_RESCUED)
+ {
+ PATH_DEBUG (tpl_text, "Ignore 'rescued' message");
+ return;
+ }
+
+ /* Check if log_id has already been logged
+ *
+ * FIXME: There is a race condition for which, right after a 'NewChannel'
+ * signal is raised and a message is received, the 'received' signal handler
+ * may be cateched before or being slower and arriving after the TplChannel
+ * preparation (in which pending message list is examined)
+ *
+ * Workaround:
+ * In the first case the analisys of P.M.L will detect that actually the
+ * handler has already received and logged the message.
+ * In the latter (here), the handler will detect that the P.M.L analisys
+ * has found and logged it, returning immediatly */
+ log_id = _tpl_create_message_token (channel_path, timestamp, msg_id);
+ if (_tpl_log_store_sqlite_log_id_is_present (index, log_id))
+ {
+ PATH_DEBUG (tpl_text, "%s found, not logging", log_id);
+ g_free (log_id);
+ goto out;
+ }
+
+ data = g_slice_new0 (ReceivedData);
+ data->msg_id = msg_id;
+ data->log_id = log_id;
+ data->type = type;
+ data->text = g_strdup (text);
+ data->timestamp = timestamp;
+
+ tp_conn = tp_channel_borrow_connection (TP_CHANNEL (tpl_text));
+ remote = g_hash_table_lookup (tpl_text->priv->contacts,
+ GUINT_TO_POINTER (sender));
+
+ if (remote == NULL)
+ {
+ /* 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));
+ }
+ else
+ {
+ keepon_on_receiving_signal (tpl_text, remote, data);
+ received_data_free (data);
+ }
+
+out:
+ g_object_unref (index);
}
-/**
- * _tpl_text_channel_new
- * @conn: TpConnection instance owning the channel
- * @object_path: the channel's DBus path
- * @tp_chan_props: channel's immutable properties, obtained for example by
- * %tp_channel_borrow_immutable_properties()
- * @account: TpAccount instance, related to the new #TplTextChannel
- * @error: location of the GError, used in case a problem is raised while
- * creating the channel
- *
- * Convenience function to create a new TPL Channel Text proxy.
- * The returned #TplTextChannel is not guaranteed to be ready at the point of
- * return.
- *
- * TplTextChannel is actually a subclass of the abstract TplChannel which is a
- * subclass of TpChannel.
- * Use #TpChannel methods, casting the #TplTextChannel instance to a
- * TpChannel, to access TpChannel data/methods from it.
- *
- * TplTextChannel is usually created using #tpl_channel_factory_build, from
- * within a #TplObserver singleton, when its Observer_Channel method is called
- * by the Channel Dispatcher.
- *
- * Returns: the TplTextChannel instance or %NULL if @object_path is not valid
- */
-TplTextChannel *
-_tpl_text_channel_new (TpConnection *conn,
- const gchar *object_path,
- GHashTable *tp_chan_props,
- TpAccount *account,
- GError **error)
+static void
+on_sent_signal_cb (TpChannel *proxy,
+ guint tp_timestamp,
+ guint type,
+ const gchar *text,
+ gpointer user_data,
+ GObject *weak_object)
{
- TpProxy *conn_proxy = TP_PROXY (conn);
+ 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;
+ gchar *log_id;
+ gint64 timestamp = (gint64) tp_timestamp;
- /* Do what tpl_channel_new does + set TplTextChannel specific properties */
+ g_return_if_fail (TPL_IS_TEXT_CHANNEL (tpl_text));
- g_return_val_if_fail (TP_IS_CONNECTION (conn), NULL);
- g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
- g_return_val_if_fail (!TPL_STR_EMPTY (object_path), NULL);
- g_return_val_if_fail (tp_chan_props != NULL, NULL);
+ channel_path = tp_proxy_get_object_path (TP_PROXY (tpl_text));
+ log_id = _tpl_create_message_token (channel_path, timestamp,
+ TPL_TEXT_EVENT_MSG_ID_ACKNOWLEDGED);
- if (!tp_dbus_check_valid_object_path (object_path, error))
- return NULL;
+ /* Initialize data for TplEntity */
+ sender = tpl_entity_new_from_tp_contact (tpl_text->priv->my_contact,
+ TPL_ENTITY_SELF);
- return g_object_new (TPL_TYPE_TEXT_CHANNEL,
- /* TplChannel properties */
+ if (!tpl_text->priv->chatroom)
+ {
+ TpContact *remote;
+ TpHandle handle = tp_channel_get_handle (TP_CHANNEL (tpl_text), NULL);
+
+ remote = g_hash_table_lookup (tpl_text->priv->contacts,
+ GUINT_TO_POINTER (handle));
+ g_assert (remote != NULL);
+
+ receiver = tpl_entity_new_from_tp_contact (remote, TPL_ENTITY_CONTACT);
+
+ DEBUG ("sent:\n\tlog_id=\"%s\"\n\tto=\"%s "
+ "(%s)\"\n\tfrom=\"%s (%s)\"\n\tmsg=\"%s\"",
+ log_id,
+ tpl_entity_get_identifier (receiver),
+ tpl_entity_get_alias (receiver),
+ tpl_entity_get_identifier (sender),
+ tpl_entity_get_alias (sender),
+ text);
+
+ }
+ else
+ {
+ receiver = tpl_entity_new_from_room_id (tpl_text->priv->chatroom_id);
+
+ DEBUG ("sent:\n\tlog_id=\"%s\"\n\tto "
+ "chatroom=\"%s\"\n\tfrom=\"%s (%s)\"\n\tmsg=\"%s\"",
+ log_id,
+ tpl_entity_get_identifier (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,
+ /* TplEvent */
"account", account,
- /* TpChannel properties */
- "connection", conn,
- "dbus-daemon", conn_proxy->dbus_daemon,
- "bus-name", conn_proxy->bus_name,
- "object-path", object_path,
- "handle-type", (guint) TP_UNKNOWN_HANDLE_TYPE,
- "channel-properties", tp_chan_props,
+ "channel-path", channel_path,
+ "log-id", log_id,
+ "receiver", receiver,
+ "sender", sender,
+ "timestamp", timestamp,
+ /* TplTextEvent */
+ "message-type", type,
+ "message", text,
+ "pending-msg-id", TPL_TEXT_EVENT_MSG_ID_ACKNOWLEDGED,
NULL);
-}
-static TpContact *
-_tpl_text_channel_get_my_contact (TplTextChannel *self)
-{
- g_return_val_if_fail (TPL_IS_TEXT_CHANNEL (self), NULL);
+ logmanager = tpl_log_manager_dup_singleton ();
+ _tpl_log_manager_add_event (logmanager, TPL_EVENT (text_log), &error);
- return self->priv->my_contact;
-}
+ if (error != NULL)
+ {
+ PATH_DEBUG (tpl_text, "LogStore: %s", error->message);
+ g_error_free (error);
+ }
-static gboolean
-_tpl_text_channel_is_chatroom (TplTextChannel *self)
-{
- g_return_val_if_fail (TPL_IS_TEXT_CHANNEL (self), FALSE);
+ g_object_unref (receiver);
+ g_object_unref (sender);
+ g_object_unref (logmanager);
+ g_object_unref (text_log);
- return self->priv->chatroom;
+ g_free (log_id);
}
-static const gchar *
-_tpl_text_channel_get_chatroom_id (TplTextChannel *self)
-{
- g_return_val_if_fail (TPL_IS_TEXT_CHANNEL (self), NULL);
-
- return self->priv->chatroom_id;
-}
static void
-_tpl_text_channel_call_when_ready (TplTextChannel *self,
- GAsyncReadyCallback cb, gpointer user_data)
+on_send_error_cb (TpChannel *proxy,
+ guint error,
+ guint timestamp,
+ guint type,
+ const gchar *text,
+ gpointer user_data,
+ GObject *weak_object)
{
- TplActionChain *actions;
-
- /* first: connect signals, so none are lost
- * second: prepare all TplChannel
- * third: cache my contact and the remote one.
- * last: check for pending messages
- *
- * 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
- * object are actually not prepared but used anyway */
- actions = _tpl_action_chain_new_async (G_OBJECT (self), cb, user_data);
- _tpl_action_chain_append (actions, pendingproc_prepare_tpl_channel, NULL);
- _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_get_room_info, NULL);
- _tpl_action_chain_append (actions, pendingproc_connect_message_signals, NULL);
- _tpl_action_chain_append (actions, pendingproc_get_pending_messages, NULL);
-#if 0
- _tpl_action_chain_append (actions, pendingproc_cleanup_pending_messages_db,
- NULL);
-#endif
- /* start the chain consuming */
- _tpl_action_chain_continue (actions);
+ 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 */
}
+
static void
-call_when_ready_wrapper (TplChannel *tpl_chan,
- GAsyncReadyCallback cb,
- gpointer user_data)
+on_lost_message_cb (TpChannel *proxy,
+ gpointer user_data,
+ GObject *weak_object)
{
- _tpl_text_channel_call_when_ready (TPL_TEXT_CHANNEL (tpl_chan), cb,
- user_data);
+ PATH_DEBUG (proxy, "lost message signal catched. nothing logged");
+ /* TODO log that the system lost a message */
}
+
+/* Signal's Callbacks */
static void
-pendingproc_prepare_tpl_channel (TplActionChain *ctx,
- gpointer user_data)
+on_pending_messages_removed_cb (TpChannel *proxy,
+ const GArray *message_ids,
+ gpointer user_data,
+ GObject *weak_object)
{
- TplChannel *tpl_chan = TPL_CHANNEL (_tpl_action_chain_get_object (ctx));
+ TplLogStore *cache = _tpl_log_store_sqlite_dup ();
+ guint i;
+ GError *error = NULL;
- TPL_CHANNEL_GET_CLASS (tpl_chan)->call_when_ready_protected (tpl_chan,
- got_tpl_chan_ready_cb, ctx);
+ for (i = 0; i < message_ids->len; ++i)
+ {
+ guint msg_id = g_array_index (message_ids, guint, i);
+ _tpl_log_store_sqlite_set_acknowledgment_by_msg_id (cache, proxy, msg_id,
+ &error);
+ if (error != NULL)
+ {
+ PATH_DEBUG (proxy, "cannot set the ACK flag for msg_id %u: %s",
+ msg_id, error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ PATH_DEBUG (proxy, "msg_id %d acknowledged", msg_id);
+ }
+ }
+
+ if (cache != NULL)
+ g_object_unref (cache);
}
static void
-got_tpl_chan_ready_cb (GObject *obj,
- GAsyncResult *tpl_chan_result,
+pendingproc_connect_message_signals (TplActionChain *ctx,
gpointer user_data)
{
- TplActionChain *ctx = user_data;
+ TplTextChannel *tpl_text = _tpl_action_chain_get_object (ctx);
+ TpChannel *channel = TP_CHANNEL (tpl_text);
+ GError *error = NULL;
- /* if TplChannel preparation is OK, keep on with the TplTextChannel */
- if (_tpl_action_chain_new_finish (tpl_chan_result))
- _tpl_action_chain_continue (ctx);
- else
- _tpl_action_chain_terminate (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)
+ 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)
+ goto disaster;
+
+ if (tp_proxy_has_interface_by_id (tpl_text,
+ TP_IFACE_QUARK_CHANNEL_INTERFACE_MESSAGES) &&
+ tp_cli_channel_interface_messages_connect_to_pending_messages_removed (
+ channel, on_pending_messages_removed_cb, NULL, NULL,
+ G_OBJECT (tpl_text), &error) == NULL)
+ goto disaster;
+
+ _tpl_action_chain_continue (ctx);
return;
+
+disaster:
+ DEBUG ("couldn't connect to signals: %s", error->message);
+ g_clear_error (&error);
+ _tpl_action_chain_terminate (ctx);
}
@@ -561,94 +732,6 @@ tpl_text_channel_clean_up_stale_tokens (TplTextChannel *self,
g_object_unref (cache);
}
-/* Cleans up stale log-ids in the index logstore.
- *
- * It 'brutally' considers as stale all log-ids which timestamp is older than
- * <time_limit> days AND are still not set as acknowledged.
- *
- * NOTE: While retrieving open channels, a partial clean-up for the channel's
- * stale pending messages is done. It's not enough, since it doesn't consider
- * all the channels being closed at retrieval time. This function tries to
- * catch stale ids in the rest of the DB, heuristically.
- *
- * It is wrong to consider all the log-ids not having an channel currently
- * open as stale, since a channel might be temporarely disconnected and
- * reconnected and some protocols might repropose not acknowledged messages on
- * reconnection. We need to consider only reasonably old log-ids.
- *
- * This function is meant only to reduce the size of the DB used for indexing.
- *
- * No _tpl_action_chain_terminate() is called if some fatal error occurs since
- * it's not considered a crucial point for TplChannel preparation.
- */
-#if 0
-static void
-pendingproc_cleanup_pending_messages_db (TplActionChain *ctx,
- gpointer user_data)
-{
- /* FIXME: https://bugs.freedesktop.org/show_bug.cgi?id=28791 */
- /* five days ago in seconds */
- TplTextChannel *self = _tpl_action_chain_get_object (ctx);
- const time_t time_limit = _tpl_time_get_current () -
- TPL_LOG_STORE_SQLITE_CLEANUP_DELTA_LIMIT;
- TplLogStore *cache = _tpl_log_store_sqlite_dup ();
- GList *l;
- GError *error = NULL;
-
- if (cache == NULL)
- {
- DEBUG ("Unable to obtain the TplLogStoreIndex singleton");
- goto out;
- }
-
- l = _tpl_log_store_sqlite_get_log_ids (cache, NULL, time_limit,
- &error);
- if (error != NULL)
- {
- DEBUG ("unable to obtain log-id in Index DB: %s", error->message);
- g_error_free (error);
- /* do not call _tpl_action_chain_terminate, if it's temporary next startup
- * TPL will re-do the clean-up. If it's fatal, the flow will stop later
- * anyway */
- goto out;
- }
-
- if (l != NULL)
- PATH_DEBUG (self, "Cleaning up stale messages");
- tpl_text_channel_clean_up_stale_tokens (self, l);
- while (l != NULL)
- {
- PATH_DEBUG (self, "%s is stale, removed from DB", (gchar *) l->data);
- g_free (l->data);
- l = g_list_delete_link (l, l);
- }
-
-out:
- if (cache != NULL)
- g_object_unref (cache);
-
- _tpl_action_chain_continue (ctx);
-}
-#endif
-
-
-static void
-pendingproc_get_pending_messages (TplActionChain *ctx,
- gpointer user_data)
-{
- TplTextChannel *chan_text = _tpl_action_chain_get_object (ctx);
-
- if (tp_proxy_has_interface_by_id (chan_text,
- TP_IFACE_QUARK_CHANNEL_INTERFACE_MESSAGES))
- tp_cli_dbus_properties_call_get (chan_text, -1,
- TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "PendingMessages",
- got_message_pending_messages_cb, ctx, NULL,
- G_OBJECT (chan_text));
- else
- tp_cli_channel_type_text_call_list_pending_messages (TP_CHANNEL (chan_text),
- -1, FALSE, got_text_pending_messages_cb, ctx, NULL, NULL);
-}
-
/* PendingMessages CB for Message interface */
static void
@@ -924,425 +1007,238 @@ got_text_pending_messages_cb (TpChannel *proxy,
_tpl_action_chain_continue (ctx);
}
+
static void
-pendingproc_connect_message_signals (TplActionChain *ctx,
+pendingproc_get_pending_messages (TplActionChain *ctx,
gpointer user_data)
{
- TplTextChannel *tpl_text = _tpl_action_chain_get_object (ctx);
- TpChannel *channel = TP_CHANNEL (tpl_text);
- GError *error = NULL;
-
- 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)
- 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)
- goto disaster;
-
- if (tp_proxy_has_interface_by_id (tpl_text,
- TP_IFACE_QUARK_CHANNEL_INTERFACE_MESSAGES) &&
- tp_cli_channel_interface_messages_connect_to_pending_messages_removed (
- channel, on_pending_messages_removed_cb, NULL, NULL,
- G_OBJECT (tpl_text), &error) == NULL)
- goto disaster;
-
- _tpl_action_chain_continue (ctx);
- return;
+ TplTextChannel *chan_text = _tpl_action_chain_get_object (ctx);
-disaster:
- DEBUG ("couldn't connect to signals: %s", error->message);
- g_clear_error (&error);
- _tpl_action_chain_terminate (ctx);
+ if (tp_proxy_has_interface_by_id (chan_text,
+ TP_IFACE_QUARK_CHANNEL_INTERFACE_MESSAGES))
+ tp_cli_dbus_properties_call_get (chan_text, -1,
+ TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "PendingMessages",
+ got_message_pending_messages_cb, ctx, NULL,
+ G_OBJECT (chan_text));
+ else
+ tp_cli_channel_type_text_call_list_pending_messages (TP_CHANNEL (chan_text),
+ -1, FALSE, got_text_pending_messages_cb, ctx, NULL, NULL);
}
-
-/* Signal's Callbacks */
+/* Cleans up stale log-ids in the index logstore.
+ *
+ * It 'brutally' considers as stale all log-ids which timestamp is older than
+ * <time_limit> days AND are still not set as acknowledged.
+ *
+ * NOTE: While retrieving open channels, a partial clean-up for the channel's
+ * stale pending messages is done. It's not enough, since it doesn't consider
+ * all the channels being closed at retrieval time. This function tries to
+ * catch stale ids in the rest of the DB, heuristically.
+ *
+ * It is wrong to consider all the log-ids not having an channel currently
+ * open as stale, since a channel might be temporarely disconnected and
+ * reconnected and some protocols might repropose not acknowledged messages on
+ * reconnection. We need to consider only reasonably old log-ids.
+ *
+ * This function is meant only to reduce the size of the DB used for indexing.
+ *
+ * No _tpl_action_chain_terminate() is called if some fatal error occurs since
+ * it's not considered a crucial point for TplChannel preparation.
+ */
+#if 0
static void
-on_pending_messages_removed_cb (TpChannel *proxy,
- const GArray *message_ids,
- gpointer user_data,
- GObject *weak_object)
+pendingproc_cleanup_pending_messages_db (TplActionChain *ctx,
+ gpointer user_data)
{
+ /* FIXME: https://bugs.freedesktop.org/show_bug.cgi?id=28791 */
+ /* five days ago in seconds */
+ TplTextChannel *self = _tpl_action_chain_get_object (ctx);
+ const time_t time_limit = _tpl_time_get_current () -
+ TPL_LOG_STORE_SQLITE_CLEANUP_DELTA_LIMIT;
TplLogStore *cache = _tpl_log_store_sqlite_dup ();
- guint i;
+ GList *l;
GError *error = NULL;
- for (i = 0; i < message_ids->len; ++i)
+ if (cache == NULL)
{
- guint msg_id = g_array_index (message_ids, guint, i);
- _tpl_log_store_sqlite_set_acknowledgment_by_msg_id (cache, proxy, msg_id,
- &error);
- if (error != NULL)
- {
- PATH_DEBUG (proxy, "cannot set the ACK flag for msg_id %u: %s",
- msg_id, error->message);
- g_clear_error (&error);
- }
- else
- {
- PATH_DEBUG (proxy, "msg_id %d acknowledged", msg_id);
- }
+ DEBUG ("Unable to obtain the TplLogStoreIndex singleton");
+ goto out;
}
- if (cache != NULL)
- g_object_unref (cache);
-}
-
-
-static void
-on_channel_invalidated_cb (TpProxy *proxy,
- guint domain,
- gint code,
- gchar *message,
- gpointer user_data)
-{
- TplChannel *tpl_chan = TPL_CHANNEL (user_data);
- TplObserver *observer = _tpl_observer_new ();
+ l = _tpl_log_store_sqlite_get_log_ids (cache, NULL, time_limit,
+ &error);
+ if (error != NULL)
+ {
+ DEBUG ("unable to obtain log-id in Index DB: %s", error->message);
+ g_error_free (error);
+ /* do not call _tpl_action_chain_terminate, if it's temporary next startup
+ * TPL will re-do the clean-up. If it's fatal, the flow will stop later
+ * anyway */
+ goto out;
+ }
- PATH_DEBUG (tpl_chan, "%s #%d %s",
- g_quark_to_string (domain), code, message);
+ if (l != NULL)
+ PATH_DEBUG (self, "Cleaning up stale messages");
+ tpl_text_channel_clean_up_stale_tokens (self, l);
+ while (l != NULL)
+ {
+ PATH_DEBUG (self, "%s is stale, removed from DB", (gchar *) l->data);
+ g_free (l->data);
+ l = g_list_delete_link (l, l);
+ }
- if (!_tpl_observer_unregister_channel (observer, tpl_chan))
- PATH_DEBUG (tpl_chan, "Channel couldn't be unregistered correctly (BUG?)");
+out:
+ if (cache != NULL)
+ g_object_unref (cache);
- g_object_unref (observer);
+ _tpl_action_chain_continue (ctx);
}
+#endif
static void
-on_lost_message_cb (TpChannel *proxy,
- gpointer user_data,
- GObject *weak_object)
+tpl_text_channel_call_when_ready (TplChannel *chan,
+ GAsyncReadyCallback cb, gpointer user_data)
{
- PATH_DEBUG (proxy, "lost message signal catched. nothing logged");
- /* TODO log that the system lost a message */
-}
-
+ TplActionChain *actions;
-static void
-on_send_error_cb (TpChannel *proxy,
- guint error,
- guint timestamp,
- guint type,
- const gchar *text,
- 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 */
+ /* first: connect signals, so none are lost
+ * second: prepare all TplChannel
+ * third: cache my contact and the remote one.
+ * last: check for pending messages
+ *
+ * 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
+ * object are actually not prepared but used anyway */
+ actions = _tpl_action_chain_new_async (G_OBJECT (chan), cb, user_data);
+ _tpl_action_chain_append (actions, pendingproc_prepare_tpl_channel, NULL);
+ _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_get_room_info, NULL);
+ _tpl_action_chain_append (actions, pendingproc_connect_message_signals, NULL);
+ _tpl_action_chain_append (actions, pendingproc_get_pending_messages, NULL);
+#if 0
+ _tpl_action_chain_append (actions, pendingproc_cleanup_pending_messages_db,
+ NULL);
+#endif
+ /* start the chain consuming */
+ _tpl_action_chain_continue (actions);
}
static void
-on_sent_signal_cb (TpChannel *proxy,
- guint tp_timestamp,
- guint type,
- const gchar *text,
- gpointer user_data,
- GObject *weak_object)
+tpl_text_channel_dispose (GObject *obj)
{
- GError *error = NULL;
- TplTextChannel *tpl_text = TPL_TEXT_CHANNEL (user_data);
- TpContact *me;
- TplEntity *sender;
- TplEntity *receiver = NULL;
- TplTextEvent *text_log;
- TplLogManager *logmanager;
- TpAccount *account;
- const gchar *channel_path;
- gchar *log_id;
- gint64 timestamp = (gint64) tp_timestamp;
-
- g_return_if_fail (TPL_IS_TEXT_CHANNEL (tpl_text));
-
- channel_path = tp_proxy_get_object_path (TP_PROXY (tpl_text));
- log_id = _tpl_create_message_token (channel_path, timestamp,
- TPL_TEXT_EVENT_MSG_ID_ACKNOWLEDGED);
-
- /* Initialize data for TplEntity */
- me = _tpl_text_channel_get_my_contact (tpl_text);
- sender = tpl_entity_new_from_tp_contact (me, TPL_ENTITY_SELF);
-
- if (!_tpl_text_channel_is_chatroom (tpl_text))
- {
- TpContact *remote;
- TpHandle handle = tp_channel_get_handle (TP_CHANNEL (tpl_text), NULL);
-
- remote = g_hash_table_lookup (tpl_text->priv->contacts,
- GUINT_TO_POINTER (handle));
- g_assert (remote != NULL);
-
- receiver = tpl_entity_new_from_tp_contact (remote, TPL_ENTITY_CONTACT);
-
- DEBUG ("sent:\n\tlog_id=\"%s\"\n\tto=\"%s "
- "(%s)\"\n\tfrom=\"%s (%s)\"\n\tmsg=\"%s\"",
- log_id,
- tpl_entity_get_identifier (receiver),
- tpl_entity_get_alias (receiver),
- tpl_entity_get_identifier (sender),
- tpl_entity_get_alias (sender),
- text);
-
- }
- else
- {
- receiver = tpl_entity_new_from_room_id (
- _tpl_text_channel_get_chatroom_id (tpl_text));
-
- DEBUG ("sent:\n\tlog_id=\"%s\"\n\tto "
- "chatroom=\"%s\"\n\tfrom=\"%s (%s)\"\n\tmsg=\"%s\"",
- log_id,
- tpl_entity_get_identifier (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,
- /* TplEvent */
- "account", account,
- "channel-path", channel_path,
- "log-id", log_id,
- "receiver", receiver,
- "sender", sender,
- "timestamp", timestamp,
- /* TplTextEvent */
- "message-type", type,
- "message", text,
- "pending-msg-id", TPL_TEXT_EVENT_MSG_ID_ACKNOWLEDGED,
- NULL);
-
- logmanager = tpl_log_manager_dup_singleton ();
- _tpl_log_manager_add_event (logmanager, TPL_EVENT (text_log), &error);
+ TplTextChannelPriv *priv = TPL_TEXT_CHANNEL (obj)->priv;
- if (error != NULL)
+ if (priv->my_contact != NULL)
{
- PATH_DEBUG (tpl_text, "LogStore: %s", error->message);
- g_error_free (error);
+ g_object_unref (priv->my_contact);
+ priv->my_contact = NULL;
}
- g_object_unref (receiver);
- g_object_unref (sender);
- g_object_unref (logmanager);
- g_object_unref (text_log);
-
- g_free (log_id);
-}
-
+ tp_clear_pointer (&priv->contacts, g_hash_table_unref);
-static void
-received_data_free (gpointer arg)
-{
- ReceivedData *data = arg;
- g_free (data->log_id);
- g_free (data->text);
- g_slice_free (ReceivedData,data);
+ G_OBJECT_CLASS (_tpl_text_channel_parent_class)->dispose (obj);
}
static void
-keepon_on_receiving_signal (TplTextChannel *tpl_text,
- TpContact *remote,
- ReceivedData *data)
+tpl_text_channel_finalize (GObject *obj)
{
- TplTextEvent *text_log;
- GError *error = NULL;
- TplLogManager *logmanager;
- TplEntity *sender;
- TplEntity *receiver;
-
- sender = tpl_entity_new_from_tp_contact (remote, TPL_ENTITY_CONTACT);
-
- if (_tpl_text_channel_is_chatroom (tpl_text))
- {
- const gchar *receiver_id = _tpl_text_channel_get_chatroom_id (tpl_text);
- receiver = tpl_entity_new_from_room_id (receiver_id);
- }
- else
- {
- TpContact *me;
- me = _tpl_text_channel_get_my_contact (tpl_text);
- receiver = tpl_entity_new_from_tp_contact (me, TPL_ENTITY_SELF);
- }
-
- /* 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)),
- "log-id", data->log_id,
- "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\tlog_id=\"%s\"\n\tto=\"%s "
- "(%s)\"\n\tfrom=\"%s (%s)\"\n\tmsg=\"%s\"",
- _tpl_event_get_log_id (TPL_EVENT (text_log)),
- 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));
+ TplTextChannelPriv *priv = TPL_TEXT_CHANNEL (obj)->priv;
- logmanager = tpl_log_manager_dup_singleton ();
- _tpl_log_manager_add_event (logmanager, TPL_EVENT (text_log), &error);
+ PATH_DEBUG (obj, "finalizing channel %p", obj);
- if (error != NULL)
- {
- DEBUG ("%s", error->message);
- g_error_free (error);
- }
+ g_free (priv->chatroom_id);
+ priv->chatroom_id = NULL;
- g_object_unref (sender);
- g_object_unref (receiver);
- g_object_unref (text_log);
- g_object_unref (logmanager);
+ G_OBJECT_CLASS (_tpl_text_channel_parent_class)->finalize (obj);
}
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)
+_tpl_text_channel_class_init (TplTextChannelClass *klass)
{
- ReceivedData *data = user_data;
- TplTextChannel *tpl_text = TPL_TEXT_CHANNEL (weak_object);
- TpContact *remote;
- TpHandle handle;
-
- if (error != 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);
- return;
- }
-
- if (n_failed > 0)
- {
- 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);
- return;
- }
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ TplChannelClass *tpl_chan_class = TPL_CHANNEL_CLASS (klass);
- remote = contacts[0];
- handle = tp_contact_get_handle (remote);
+ object_class->dispose = tpl_text_channel_dispose;
+ object_class->finalize = tpl_text_channel_finalize;
- g_hash_table_insert (tpl_text->priv->contacts, GUINT_TO_POINTER (handle),
- g_object_ref (remote));
+ tpl_chan_class->call_when_ready = tpl_text_channel_call_when_ready;
- keepon_on_receiving_signal (tpl_text, remote, data);
+ g_type_class_add_private (object_class, sizeof (TplTextChannelPriv));
}
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)
+_tpl_text_channel_init (TplTextChannel *self)
{
- TplTextChannel *tpl_text = TPL_TEXT_CHANNEL (proxy);
- TpConnection *tp_conn;
- TpContact *remote;
- TplLogStore *index = _tpl_log_store_sqlite_dup ();
- const gchar *channel_path = tp_proxy_get_object_path (TP_PROXY (tpl_text));
- gchar *log_id;
- ReceivedData *data;
+ TplTextChannelPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ TPL_TYPE_TEXT_CHANNEL, TplTextChannelPriv);
- /* 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;
- }
+ self->priv = priv;
- if (flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_RESCUED)
- {
- PATH_DEBUG (tpl_text, "Ignore 'rescued' message");
- return;
- }
+ self->priv->contacts = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) g_object_unref);
+}
- /* Check if log_id has already been logged
- *
- * FIXME: There is a race condition for which, right after a 'NewChannel'
- * signal is raised and a message is received, the 'received' signal handler
- * may be cateched before or being slower and arriving after the TplChannel
- * preparation (in which pending message list is examined)
- *
- * Workaround:
- * In the first case the analisys of P.M.L will detect that actually the
- * handler has already received and logged the message.
- * In the latter (here), the handler will detect that the P.M.L analisys
- * has found and logged it, returning immediatly */
- log_id = _tpl_create_message_token (channel_path, timestamp, msg_id);
- if (_tpl_log_store_sqlite_log_id_is_present (index, log_id))
- {
- PATH_DEBUG (tpl_text, "%s found, not logging", log_id);
- g_free (log_id);
- goto out;
- }
- data = g_slice_new0 (ReceivedData);
- data->msg_id = msg_id;
- data->log_id = log_id;
- data->type = type;
- data->text = g_strdup (text);
- data->timestamp = timestamp;
+/**
+ * _tpl_text_channel_new
+ * @conn: TpConnection instance owning the channel
+ * @object_path: the channel's DBus path
+ * @tp_chan_props: channel's immutable properties, obtained for example by
+ * %tp_channel_borrow_immutable_properties()
+ * @account: TpAccount instance, related to the new #TplTextChannel
+ * @error: location of the GError, used in case a problem is raised while
+ * creating the channel
+ *
+ * Convenience function to create a new TPL Channel Text proxy.
+ * The returned #TplTextChannel is not guaranteed to be ready at the point of
+ * return.
+ *
+ * TplTextChannel is actually a subclass of the abstract TplChannel which is a
+ * subclass of TpChannel.
+ * Use #TpChannel methods, casting the #TplTextChannel instance to a
+ * TpChannel, to access TpChannel data/methods from it.
+ *
+ * TplTextChannel is usually created using #tpl_channel_factory_build, from
+ * within a #TplObserver singleton, when its Observer_Channel method is called
+ * by the Channel Dispatcher.
+ *
+ * Returns: the TplTextChannel instance or %NULL if @object_path is not valid
+ */
+TplTextChannel *
+_tpl_text_channel_new (TpConnection *conn,
+ const gchar *object_path,
+ GHashTable *tp_chan_props,
+ TpAccount *account,
+ GError **error)
+{
+ TpProxy *conn_proxy = TP_PROXY (conn);
- tp_conn = tp_channel_borrow_connection (TP_CHANNEL (tpl_text));
- remote = g_hash_table_lookup (tpl_text->priv->contacts,
- GUINT_TO_POINTER (sender));
+ /* Do what tpl_channel_new does + set TplTextChannel specific properties */
- if (remote == NULL)
- {
- /* 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));
- }
- else
- {
- keepon_on_receiving_signal (tpl_text, remote, data);
- received_data_free (data);
- }
+ g_return_val_if_fail (TP_IS_CONNECTION (conn), NULL);
+ g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
+ g_return_val_if_fail (!TPL_STR_EMPTY (object_path), NULL);
+ g_return_val_if_fail (tp_chan_props != NULL, NULL);
-out:
- g_object_unref (index);
+ if (!tp_dbus_check_valid_object_path (object_path, error))
+ return NULL;
+
+ return g_object_new (TPL_TYPE_TEXT_CHANNEL,
+ /* TplChannel properties */
+ "account", account,
+ /* TpChannel properties */
+ "connection", conn,
+ "dbus-daemon", conn_proxy->dbus_daemon,
+ "bus-name", conn_proxy->bus_name,
+ "object-path", object_path,
+ "handle-type", (guint) TP_UNKNOWN_HANDLE_TYPE,
+ "channel-properties", tp_chan_props,
+ NULL);
}