diff options
Diffstat (limited to 'tests/lib/echo-chan.c')
-rw-r--r-- | tests/lib/echo-chan.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/tests/lib/echo-chan.c b/tests/lib/echo-chan.c new file mode 100644 index 0000000..868fbcf --- /dev/null +++ b/tests/lib/echo-chan.c @@ -0,0 +1,223 @@ +/* + * chan.c - an example text channel talking to a particular + * contact. Similar code is used for 1-1 IM channels in many protocols + * (IRC private messages ("/query"), XMPP IM etc.) + * + * Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2007 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "echo-chan.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +static void destroyable_iface_init (gpointer iface, gpointer data); + +G_DEFINE_TYPE_WITH_CODE (TpTestsEchoChannel, + tp_tests_echo_channel, + TP_TYPE_BASE_CHANNEL, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT, + tp_message_mixin_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_DESTROYABLE, + destroyable_iface_init); + ) + +/* type definition stuff */ + +static GPtrArray * +tp_tests_echo_channel_get_interfaces (TpBaseChannel *self) +{ + GPtrArray *interfaces; + + interfaces = TP_BASE_CHANNEL_CLASS (tp_tests_echo_channel_parent_class)-> + get_interfaces (self); + + g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_DESTROYABLE); + return interfaces; +}; + +static void +tp_tests_echo_channel_init (TpTestsEchoChannel *self) +{ +} + +static void text_send (GObject *object, TpMessage *message, + TpMessageSendingFlags flags); + +static void +constructed (GObject *object) +{ + TpTestsEchoChannel *self = TP_TESTS_ECHO_CHANNEL (object); + TpBaseConnection *conn = tp_base_channel_get_connection (TP_BASE_CHANNEL (self)); + const TpChannelTextMessageType types[] = { + TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, + TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION, + TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, + }; + const gchar * supported_content_types[] = { + "text/plain", + NULL + }; + g_assert (conn != NULL); + + G_OBJECT_CLASS (tp_tests_echo_channel_parent_class)->constructed (object); + + tp_base_channel_register (TP_BASE_CHANNEL (self)); + + tp_message_mixin_init (object, + G_STRUCT_OFFSET (TpTestsEchoChannel, message), + conn); + tp_message_mixin_implement_sending (object, + text_send, G_N_ELEMENTS (types), types, 0, 0, + supported_content_types); +} + +static void +finalize (GObject *object) +{ + tp_message_mixin_finalize (object); + + ((GObjectClass *) tp_tests_echo_channel_parent_class)->finalize (object); +} + +static void +tp_tests_echo_channel_close (TpTestsEchoChannel *self) +{ + GObject *object = (GObject *) self; + gboolean closed = tp_base_channel_is_destroyed (TP_BASE_CHANNEL (self)); + + if (!closed) + { + TpHandle first_sender; + + /* The manager wants to be able to respawn the channel if it has pending + * messages. When respawned, the channel must have the initiator set + * to the contact who sent us those messages (if it isn't already), + * and the messages must be marked as having been rescued so they + * don't get logged twice. */ + if (tp_message_mixin_has_pending_messages (object, &first_sender)) + { + tp_base_channel_reopened (TP_BASE_CHANNEL (self), first_sender); + tp_message_mixin_set_rescued (object); + } + else + { + tp_base_channel_destroyed (TP_BASE_CHANNEL (self)); + } + } +} + +static void +channel_close (TpBaseChannel *channel) +{ + TpTestsEchoChannel *self = TP_TESTS_ECHO_CHANNEL (channel); + + tp_tests_echo_channel_close (self); +} + +static void +tp_tests_echo_channel_class_init (TpTestsEchoChannelClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); + + object_class->constructed = constructed; + object_class->finalize = finalize; + + base_class->channel_type = TP_IFACE_CHANNEL_TYPE_TEXT; + base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT; + base_class->get_interfaces = tp_tests_echo_channel_get_interfaces; + base_class->close = channel_close; + + tp_message_mixin_init_dbus_properties (object_class); +} + + +static void +text_send (GObject *object, + TpMessage *message, + TpMessageSendingFlags flags) +{ + TpTestsEchoChannel *self = TP_TESTS_ECHO_CHANNEL (object); + TpChannelTextMessageType type = tp_message_get_message_type (message); + TpChannelTextMessageType echo_type = type; + TpHandle target = tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self)); + gchar *echo; + gint64 now = time (NULL); + const GHashTable *part; + const gchar *text; + TpMessage *msg; + + /* Pretend that the remote contact has replied. Normally, you'd + * call tp_text_mixin_receive or tp_text_mixin_receive_with_flags + * in response to network events */ + + part = tp_message_peek (message, 1); + text = tp_asv_get_string (part, "content"); + + switch (type) + { + case TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL: + echo = g_strdup_printf ("You said: %s", text); + break; + case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION: + echo = g_strdup_printf ("notices that the user %s", text); + break; + case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE: + echo = g_strdup_printf ("You sent a notice: %s", text); + break; + default: + echo = g_strdup_printf ("You sent some weird message type, %u: \"%s\"", + type, text); + echo_type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL; + } + + tp_message_mixin_sent (object, message, 0, "", NULL); + + msg = tp_cm_message_new ( + tp_base_channel_get_connection (TP_BASE_CHANNEL (self)), + 2); + + tp_cm_message_set_sender (msg, target); + tp_message_set_uint32 (msg, 0, "message-type", echo_type); + tp_message_set_int64 (msg, 0, "message-sent", now); + tp_message_set_int64 (msg, 0, "message-received", now); + + tp_message_set_string (msg, 1, "content-type", "text/plain"); + tp_message_set_string (msg, 1, "content", echo); + + tp_message_mixin_take_received (object, msg); + + g_free (echo); +} + +static void +destroyable_destroy (TpSvcChannelInterfaceDestroyable *iface, + DBusGMethodInvocation *context) +{ + TpTestsEchoChannel *self = TP_TESTS_ECHO_CHANNEL (iface); + + tp_message_mixin_clear ((GObject *) self); + tp_base_channel_destroyed (TP_BASE_CHANNEL (self)); + + tp_svc_channel_interface_destroyable_return_from_destroy (context); +} + +static void +destroyable_iface_init (gpointer iface, + gpointer data) +{ + TpSvcChannelInterfaceDestroyableClass *klass = iface; + +#define IMPLEMENT(x) \ + tp_svc_channel_interface_destroyable_implement_##x (klass, destroyable_##x) + IMPLEMENT (destroy); +#undef IMPLEMENT +} |