diff options
author | Will Thompson <will.thompson@collabora.co.uk> | 2012-01-26 13:09:47 +0000 |
---|---|---|
committer | Will Thompson <will.thompson@collabora.co.uk> | 2012-01-26 13:09:47 +0000 |
commit | e142bebe3e112d715af2b4784b24730eb9c310a0 (patch) | |
tree | 594393ed618bf82b4600f61c624de58ad3340ca1 /src/muc-factory.c | |
parent | a2a603bdfb12bc9aa80726bf1f822cc22c76917e (diff) | |
parent | 035a6b0a6e8ce1787abf2583bb918436282026fe (diff) | |
download | telepathy-gabble-e142bebe3e112d715af2b4784b24730eb9c310a0.tar.gz |
Merge branch 'master' into BYE-BYE-LOUDMOUTH
Conflicts:
src/connection.c
src/connection.h
src/ft-manager.c
src/jingle-content.c
src/jingle-factory.c
src/jingle-session.c
src/message-util.c
src/muc-channel.c
src/muc-channel.h
Diffstat (limited to 'src/muc-factory.c')
-rw-r--r-- | src/muc-factory.c | 338 |
1 files changed, 209 insertions, 129 deletions
diff --git a/src/muc-factory.c b/src/muc-factory.c index b6bb486d5..f5c324968 100644 --- a/src/muc-factory.c +++ b/src/muc-factory.c @@ -20,13 +20,12 @@ #include "config.h" #include "muc-factory.h" -#define DBUS_API_SUBJECT_TO_CHANGE - #include <string.h> #include <dbus/dbus-glib.h> #include <dbus/dbus-glib-lowlevel.h> #include <loudmouth/loudmouth.h> +#include <wocky/wocky-utils.h> #include <telepathy-glib/channel-manager.h> #include <telepathy-glib/dbus.h> #include <telepathy-glib/interfaces.h> @@ -36,7 +35,7 @@ #define DEBUG_FLAG GABBLE_DEBUG_MUC -#include "caps-channel-manager.h" +#include "gabble/caps-channel-manager.h" #include "connection.h" #include "conn-olpc.h" #include "debug.h" @@ -99,17 +98,14 @@ struct _GabbleMucFactoryPrivate gboolean dispose_has_run; }; -#define GABBLE_MUC_FACTORY_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), GABBLE_TYPE_MUC_FACTORY, \ - GabbleMucFactoryPrivate)) - static GObject *gabble_muc_factory_constructor (GType type, guint n_props, GObjectConstructParam *props); static void gabble_muc_factory_init (GabbleMucFactory *fac) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (fac, + GABBLE_TYPE_MUC_FACTORY, GabbleMucFactoryPrivate); fac->priv = priv; @@ -150,7 +146,7 @@ static void gabble_muc_factory_dispose (GObject *object) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (object); - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; if (priv->dispose_has_run) return; @@ -166,7 +162,7 @@ gabble_muc_factory_dispose (GObject *object) g_hash_table_foreach (priv->disco_requests, cancel_disco_request, priv->conn->disco); - g_hash_table_destroy (priv->disco_requests); + g_hash_table_unref (priv->disco_requests); if (G_OBJECT_CLASS (gabble_muc_factory_parent_class)->dispose) G_OBJECT_CLASS (gabble_muc_factory_parent_class)->dispose (object); @@ -179,7 +175,7 @@ gabble_muc_factory_get_property (GObject *object, GParamSpec *pspec) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (object); - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; switch (property_id) { case PROP_CONNECTION: @@ -198,7 +194,7 @@ gabble_muc_factory_set_property (GObject *object, GParamSpec *pspec) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (object); - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; switch (property_id) { case PROP_CONNECTION: @@ -242,7 +238,7 @@ static void muc_channel_closed_cb (GabbleMucChannel *chan, gpointer user_data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data); - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; TpHandle room_handle; tp_channel_manager_emit_channel_closed_for_object (fac, @@ -265,7 +261,7 @@ muc_ready_cb (GabbleMucChannel *text_chan, gpointer data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data); - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; GabbleTubesChannel *tubes_chan; GSList *requests_satisfied_text, *requests_satisfied_tubes = NULL; gboolean text_requested; @@ -340,7 +336,7 @@ muc_ready_cb (GabbleMucChannel *text_chan, tp_channel_manager_emit_new_channels (fac, channels); - g_hash_table_destroy (channels); + g_hash_table_unref (channels); } g_hash_table_remove (priv->tubes_needed_for_tube, tubes_chan); @@ -354,7 +350,7 @@ muc_join_error_cb (GabbleMucChannel *chan, gpointer data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data); - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; GabbleTubesChannel *tubes_chan; GSList *requests_satisfied; GSList *iter; @@ -452,9 +448,10 @@ new_muc_channel (GabbleMucFactory *fac, gboolean requested, GHashTable *initial_channels, GArray *initial_handles, - char **initial_ids) + char **initial_ids, + const char *room_name) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; GabbleMucChannel *chan; char *object_path; @@ -497,6 +494,7 @@ new_muc_channel (GabbleMucFactory *fac, "initial-channels", initial_channels_array, "initial-invitee-handles", initial_handles, "initial-invitee-ids", initial_ids, + "room-name", room_name, NULL); g_signal_connect (chan, "closed", (GCallback) muc_channel_closed_cb, fac); @@ -507,7 +505,7 @@ new_muc_channel (GabbleMucFactory *fac, g_hash_table_insert (priv->text_channels, GUINT_TO_POINTER (handle), chan); g_free (object_path); - g_ptr_array_free (initial_channels_array, TRUE); + g_ptr_array_unref (initial_channels_array); g_array_unref (initial_handles); if (_gabble_muc_channel_is_ready (chan)) @@ -529,7 +527,7 @@ do_invite (GabbleMucFactory *fac, TpHandle inviter_handle, const gchar *reason) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM); TpHandle room_handle; @@ -547,7 +545,7 @@ do_invite (GabbleMucFactory *fac, GUINT_TO_POINTER (room_handle)) == NULL) { new_muc_channel (fac, room_handle, TRUE, inviter_handle, reason, FALSE, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); } else { @@ -581,7 +579,7 @@ obsolete_invite_disco_cb (GabbleDisco *self, struct DiscoInviteData *data = (struct DiscoInviteData *) user_data; GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data->factory); - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); WockyNode *identity; @@ -626,7 +624,7 @@ process_muc_invite (GabbleMucFactory *fac, const gchar *from, TpChannelTextSendError send_error) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); @@ -700,7 +698,7 @@ process_obsolete_invite (GabbleMucFactory *fac, const gchar *body, TpChannelTextSendError send_error) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); @@ -788,7 +786,7 @@ muc_factory_message_cb (LmMessageHandler *handler, gpointer user_data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data); - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; const gchar *from, *body, *id; time_t stamp; @@ -824,7 +822,7 @@ muc_factory_message_cb (LmMessageHandler *handler, void gabble_muc_factory_broadcast_presence (GabbleMucFactory *self) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; GHashTableIter iter; gpointer channel = NULL; @@ -842,7 +840,7 @@ gabble_muc_factory_associate_request (GabbleMucFactory *self, gpointer channel, gpointer request) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; GSList *list = g_hash_table_lookup (priv->queued_requests, channel); g_assert (TP_IS_EXPORTABLE_CHANNEL (channel)); @@ -880,7 +878,7 @@ cancel_queued_requests (gpointer k, static void gabble_muc_factory_close_all (GabbleMucFactory *self) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; DEBUG ("closing channels"); @@ -895,9 +893,9 @@ gabble_muc_factory_close_all (GabbleMucFactory *self) g_hash_table_foreach_steal (priv->queued_requests, cancel_queued_requests, self); - tp_clear_pointer (&priv->queued_requests, g_hash_table_destroy); - tp_clear_pointer (&priv->text_needed_for_tubes, g_hash_table_destroy); - tp_clear_pointer (&priv->tubes_needed_for_tube, g_hash_table_destroy); + tp_clear_pointer (&priv->queued_requests, g_hash_table_unref); + tp_clear_pointer (&priv->text_needed_for_tubes, g_hash_table_unref); + tp_clear_pointer (&priv->tubes_needed_for_tube, g_hash_table_unref); /* Use a temporary variable because we don't want * muc_channel_closed_cb or tubes_channel_closed_cb to remove the channel @@ -914,7 +912,7 @@ gabble_muc_factory_close_all (GabbleMucFactory *self) while (g_hash_table_iter_next (&iter, NULL, &chan)) gabble_muc_channel_teardown (GABBLE_MUC_CHANNEL (chan)); - g_hash_table_destroy (tmp); + g_hash_table_unref (tmp); } if (priv->message_cb != NULL) @@ -935,7 +933,7 @@ connection_status_changed_cb (GabbleConnection *conn, guint reason, GabbleMucFactory *self) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; switch (status) { @@ -964,7 +962,7 @@ gabble_muc_factory_constructor (GType type, guint n_props, GObject *obj = G_OBJECT_CLASS (gabble_muc_factory_parent_class)-> constructor (type, n_props, props); GabbleMucFactory *self = GABBLE_MUC_FACTORY (obj); - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; priv->status_changed_id = g_signal_connect (priv->conn, "status-changed", (GCallback) connection_status_changed_cb, obj); @@ -1009,7 +1007,7 @@ gabble_muc_factory_foreach_channel (TpChannelManager *manager, gpointer user_data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (manager); - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac); + GabbleMucFactoryPrivate *priv = fac->priv; struct _ForeachData data; data.user_data = user_data; @@ -1035,7 +1033,8 @@ ensure_muc_channel (GabbleMucFactory *fac, gboolean requested, GHashTable *initial_channels, GArray *initial_handles, - char **initial_ids) + char **initial_ids, + const char *room_name) { TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn; @@ -1044,7 +1043,7 @@ ensure_muc_channel (GabbleMucFactory *fac, if (*ret == NULL) { *ret = new_muc_channel (fac, handle, FALSE, base_conn->self_handle, NULL, - requested, initial_channels, initial_handles, initial_ids); + requested, initial_channels, initial_handles, initial_ids, room_name); return FALSE; } @@ -1062,7 +1061,7 @@ gabble_muc_factory_handle_si_stream_request (GabbleMucFactory *self, const gchar *stream_id, LmMessage *msg) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM); GabbleMucChannel *gmuc = NULL; @@ -1092,15 +1091,15 @@ GabbleMucChannel * gabble_muc_factory_find_text_channel (GabbleMucFactory *self, TpHandle handle) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; return g_hash_table_lookup (priv->text_channels, GUINT_TO_POINTER (handle)); } static const gchar * const muc_channel_fixed_properties[] = { - TP_IFACE_CHANNEL ".ChannelType", - TP_IFACE_CHANNEL ".TargetHandleType", + TP_PROP_CHANNEL_CHANNEL_TYPE, + TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL }; @@ -1108,18 +1107,20 @@ static const gchar * const * muc_tubes_channel_fixed_properties = muc_channel_fixed_properties; static const gchar * const muc_channel_allowed_properties[] = { - TP_IFACE_CHANNEL ".TargetHandle", - TP_IFACE_CHANNEL ".TargetID", - TP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialChannels", - TP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialInviteeHandles", - TP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialInviteeIDs", - TP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InvitationMessage", + TP_PROP_CHANNEL_TARGET_HANDLE, + TP_PROP_CHANNEL_TARGET_ID, + TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_CHANNELS, + TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_HANDLES, + TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_IDS, + TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INVITATION_MESSAGE, + TP_PROP_CHANNEL_INTERFACE_ROOM_ROOM_NAME, + TP_PROP_CHANNEL_INTERFACE_ROOM_SERVER, NULL }; static const gchar * const muc_tubes_channel_allowed_properties[] = { - TP_IFACE_CHANNEL ".TargetHandle", - TP_IFACE_CHANNEL ".TargetID", + TP_PROP_CHANNEL_TARGET_HANDLE, + TP_PROP_CHANNEL_TARGET_ID, NULL }; @@ -1134,12 +1135,12 @@ gabble_muc_factory_type_foreach_channel_class (GType type, channel_type_value = tp_g_value_slice_new (G_TYPE_STRING); /* no string value yet - we'll change it for each channel class */ - g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType", + g_hash_table_insert (table, TP_PROP_CHANNEL_CHANNEL_TYPE, channel_type_value); handle_type_value = tp_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (handle_type_value, TP_HANDLE_TYPE_ROOM); - g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType", + g_hash_table_insert (table, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, handle_type_value); /* Channel.Type.Text */ @@ -1171,7 +1172,7 @@ gabble_muc_factory_type_foreach_channel_class (GType type, gabble_media_factory_call_channel_allowed_properties (), user_data); - g_hash_table_destroy (table); + g_hash_table_unref (table); } /* return TRUE if the text_channel associated is ready */ @@ -1181,14 +1182,14 @@ ensure_tubes_channel (GabbleMucFactory *self, GabbleTubesChannel **tubes_chan, gboolean requested) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn; GabbleMucChannel *text_chan; TpHandle initiator = base_conn->self_handle; gboolean result; result = ensure_muc_channel (self, priv, handle, &text_chan, FALSE, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); /* this refs the tube channel object */ *tubes_chan = gabble_muc_channel_open_tube (text_chan, initiator, requested); @@ -1207,7 +1208,7 @@ handle_text_channel_request (GabbleMucFactory *self, TpHandle room, GError **error) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; TpBaseConnection *conn = TP_BASE_CONNECTION (priv->conn); GabbleMucChannel *text_chan; TpHandleSet *handles; @@ -1226,22 +1227,29 @@ handle_text_channel_request (GabbleMucFactory *self, char **initial_ids, **final_ids; const char *invite_msg; + const gchar *room_name, *server_prop; + if (tp_channel_manager_asv_has_unknown_properties (request_properties, muc_channel_fixed_properties, muc_channel_allowed_properties, error)) return FALSE; initial_channels = tp_asv_get_boxed (request_properties, - TP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialChannels", + TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_CHANNELS, TP_ARRAY_TYPE_OBJECT_PATH_LIST); initial_handles = tp_asv_get_boxed (request_properties, - TP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialInviteeHandles", + TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_HANDLES, DBUS_TYPE_G_UINT_ARRAY); initial_ids = tp_asv_get_boxed (request_properties, - TP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialInviteeIDs", + TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_IDS, G_TYPE_STRV); invite_msg = tp_asv_get_string (request_properties, - TP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InvitationMessage"); + TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INVITATION_MESSAGE); + + room_name = tp_asv_get_string (request_properties, + TP_PROP_CHANNEL_INTERFACE_ROOM_ROOM_NAME); + server_prop = tp_asv_get_string (request_properties, + TP_PROP_CHANNEL_INTERFACE_ROOM_SERVER); handles = tp_handle_set_new (contact_handles); continue_handles = tp_intset_new (); @@ -1339,9 +1347,11 @@ handle_text_channel_request (GabbleMucFactory *self, final_ids[i] = (char *) id; } + /* TargetHandleType=None and TargetHandle=0 */ if (room == 0) { char *uuid, *id, *server = ""; + gchar *tmp = NULL; /* There's no super obvious way to tell.. you can't invite GMail users to * a non-Google MUC (it just doesn't work), and if your own account is on @@ -1365,15 +1375,29 @@ handle_text_channel_request (GabbleMucFactory *self, } } - uuid = gabble_generate_id (); - id = g_strdup_printf ("private-chat-%s%s", uuid, server); + if (server_prop != NULL) + { + tmp = g_strdup_printf ("@%s", server_prop); + server = tmp; + } - DEBUG ("Creating PMUC '%s'", id); + if (room_name != NULL && room_name[0] != '\0') + { + id = g_strdup_printf ("%s%s", room_name, server); + } + else + { + uuid = gabble_generate_id (); + id = g_strdup_printf ("private-chat-%s%s", uuid, server); + g_free (uuid); + + DEBUG ("Creating PMUC '%s'", id); + } room = tp_handle_ensure (room_handles, id, NULL, error); - g_free (uuid); g_free (id); + g_free (tmp); if (room == 0) { @@ -1387,8 +1411,66 @@ handle_text_channel_request (GabbleMucFactory *self, tp_handle_ref (room_handles, room); } + /* Make sure TargetID and RoomName don't conflict. */ + if (room_name != NULL && room_name[0] != '\0') + { + const gchar *target_id = tp_handle_inspect (room_handles, room); + gchar *target_room = NULL; + gboolean ok; + + /* JIDs that are handles must already be valid. */ + ok = wocky_decode_jid (target_id, &target_room, NULL, NULL); + g_assert (ok); + + ok = !tp_strdiff (target_room, room_name); + + if (!ok) + { + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "TargetID's node part (%s) doesn't match RoomName (%s)", + target_room, room_name); + ret = FALSE; + } + + g_free (target_room); + + if (!ok) + goto out; + } + + /* Make sure TargetID and Server don't conflict. */ + if (server_prop != NULL) + { + const gchar *target_id = tp_handle_inspect (room_handles, room); + gchar *target_server = NULL; + gboolean ok = TRUE; + + /* JIDs that are handles must already be valid. */ + ok = wocky_decode_jid (target_id, NULL, &target_server, NULL); + g_assert (ok); + + if (target_server != NULL) + ok = !tp_strdiff (target_server, server_prop); + else + ok = TRUE; + + if (!ok) + { + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "TargetID's domain part (%s) doesn't match Server (%s)", + target_server, server_prop); + ret = FALSE; + } + + g_free (target_server); + + if (!ok) + goto out; + + } + if (ensure_muc_channel (self, priv, room, &text_chan, TRUE, - final_channels, final_handles, final_ids)) + final_channels, final_handles, final_ids, room_name)) { /* channel exists */ @@ -1454,8 +1536,8 @@ out: if (room != 0) tp_handle_unref (room_handles, room); - g_hash_table_destroy (final_channels); - g_array_free (final_handles, TRUE); + g_hash_table_unref (final_channels); + g_array_unref (final_handles); g_free (final_ids); tp_handle_set_destroy (handles); @@ -1472,7 +1554,7 @@ handle_tubes_channel_request (GabbleMucFactory *self, TpHandle handle, GError **error) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; GabbleTubesChannel *tube = NULL; GabbleMucChannel *gmuc = NULL; @@ -1529,7 +1611,7 @@ handle_tube_channel_request (GabbleMucFactory *self, GError **error) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; gboolean can_announce_now = TRUE; gboolean tubes_channel_created = FALSE; GabbleTubesChannel *tube = NULL; @@ -1575,7 +1657,7 @@ handle_tube_channel_request (GabbleMucFactory *self, g_hash_table_insert (channels, new_channel, request_tokens); tp_channel_manager_emit_new_channels (self, channels); - g_hash_table_destroy (channels); + g_hash_table_unref (channels); g_slist_free (request_tokens); } else @@ -1617,12 +1699,12 @@ handle_stream_tube_channel_request (GabbleMucFactory *self, /* "Service" is a mandatory, not-fixed property */ service = tp_asv_get_string (request_properties, - TP_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service"); + TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE); if (service == NULL) { g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, "Request does not contain the mandatory property '%s'", - TP_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service"); + TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE); return FALSE; } @@ -1648,12 +1730,12 @@ handle_dbus_tube_channel_request (GabbleMucFactory *self, /* "ServiceName" is a mandatory, not-fixed property */ service = tp_asv_get_string (request_properties, - TP_IFACE_CHANNEL_TYPE_DBUS_TUBE ".ServiceName"); + TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME); if (service == NULL) { g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, "Request does not contain the mandatory property '%s'", - TP_IFACE_CHANNEL_TYPE_DBUS_TUBE ".ServiceName"); + TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME); return FALSE; } @@ -1695,7 +1777,7 @@ handle_call_channel_request (GabbleMucFactory *self, TpHandle handle, GError **error) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; gboolean initial_audio, initial_video; GabbleMucChannel *muc; GabbleCallMucChannel *call; @@ -1719,7 +1801,7 @@ handle_call_channel_request (GabbleMucFactory *self, return FALSE; } - ensure_muc_channel (self, priv, handle, &muc, FALSE, NULL, NULL, NULL); + ensure_muc_channel (self, priv, handle, &muc, FALSE, NULL, NULL, NULL, NULL); call = gabble_muc_channel_get_call (muc); @@ -1758,6 +1840,27 @@ error: return FALSE; } +typedef gboolean (*ChannelTypeHandlerFunc) ( + GabbleMucFactory *self, + gpointer request_token, + GHashTable *request_properties, + gboolean require_new, + TpHandle room, + GError **error); + +typedef struct { + const gchar *channel_type; + ChannelTypeHandlerFunc f; +} ChannelTypeHandler; + +static ChannelTypeHandler channel_type_handlers[] = { + { TP_IFACE_CHANNEL_TYPE_TEXT, handle_text_channel_request }, + { TP_IFACE_CHANNEL_TYPE_TUBES, handle_tubes_channel_request }, + { TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, handle_stream_tube_channel_request }, + { TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, handle_dbus_tube_channel_request }, + { TPY_IFACE_CHANNEL_TYPE_CALL, handle_call_channel_request }, + { NULL } +}; static gboolean gabble_muc_factory_request (GabbleMucFactory *self, @@ -1768,80 +1871,57 @@ gabble_muc_factory_request (GabbleMucFactory *self, GError *error = NULL; TpHandleType handle_type; TpHandle handle; - gboolean conference; + gboolean conference, room; const gchar *channel_type; + ChannelTypeHandler *h; handle_type = tp_asv_get_uint32 (request_properties, - TP_IFACE_CHANNEL ".TargetHandleType", NULL); + TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL); channel_type = tp_asv_get_string (request_properties, - TP_IFACE_CHANNEL ".ChannelType"); + TP_PROP_CHANNEL_CHANNEL_TYPE); /* Conference channels can be anonymous (HandleTypeNone) */ conference = (handle_type == TP_HANDLE_TYPE_NONE && !tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT) && (g_hash_table_lookup (request_properties, - TP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialChannels") || + TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_CHANNELS) || g_hash_table_lookup (request_properties, - TP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialInviteeHandles") || + TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_HANDLES) || g_hash_table_lookup (request_properties, - TP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialInviteeIDs"))); + TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_IDS))); - /* the channel must either be a room, or a new conference */ - if (handle_type != TP_HANDLE_TYPE_ROOM && !conference) - return FALSE; + room = (handle_type == TP_HANDLE_TYPE_NONE + && !tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT) + && g_hash_table_lookup (request_properties, + TP_PROP_CHANNEL_INTERFACE_ROOM_ROOM_NAME)); - if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT) && - tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES) && - tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE) && - tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE) && - tp_strdiff (channel_type, TPY_IFACE_CHANNEL_TYPE_CALL)) + /* the channel must either be a room, or a new conference */ + if (handle_type != TP_HANDLE_TYPE_ROOM && !conference && !room) return FALSE; /* validity already checked by TpBaseConnection */ handle = tp_asv_get_uint32 (request_properties, - TP_IFACE_CHANNEL ".TargetHandle", NULL); - g_assert (conference || handle != 0); + TP_PROP_CHANNEL_TARGET_HANDLE, NULL); + g_assert (conference || room || handle != 0); - if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT)) + for (h = channel_type_handlers; h->channel_type != NULL; h++) { - if (handle_text_channel_request (self, request_token, - request_properties, require_new, handle, &error)) - return TRUE; - } - else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES)) - { - if (handle_tubes_channel_request (self, request_token, - request_properties, require_new, handle, &error)) - return TRUE; - } - else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE)) - { - if (handle_stream_tube_channel_request (self, request_token, - request_properties, require_new, handle, &error)) - return TRUE; - } - else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE)) - { - if (handle_dbus_tube_channel_request (self, request_token, - request_properties, require_new, handle, &error)) - return TRUE; - } - else if (!tp_strdiff (channel_type, TPY_IFACE_CHANNEL_TYPE_CALL)) - { - if (handle_call_channel_request (self, request_token, - request_properties, require_new, handle, &error)) - return TRUE; - } - else - { - g_assert_not_reached (); + if (tp_strdiff (channel_type, h->channel_type)) + continue; + + if (!h->f (self, request_token, request_properties, require_new, + handle, &error)) + { + tp_channel_manager_emit_request_failed (self, request_token, + error->domain, error->code, error->message); + g_error_free (error); + } + + /* We've handled the request one way or another. */ + return TRUE; } - /* Something failed */ - tp_channel_manager_emit_request_failed (self, request_token, - error->domain, error->code, error->message); - g_error_free (error); - return TRUE; + return FALSE; } @@ -1884,7 +1964,7 @@ gboolean gabble_muc_factory_handle_jingle_session (GabbleMucFactory *self, GabbleJingleSession *session) { - GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); + GabbleMucFactoryPrivate *priv = self->priv; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM); TpHandle room; |