summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2009-11-27 12:26:50 +0000
committerWill Thompson <will.thompson@collabora.co.uk>2009-11-27 12:26:50 +0000
commit0b0506542442aa801fdf21afa5f880cf6320bc05 (patch)
tree34354bb0392286b5113f3dc3212180fff2c752d4 /src
parent2ee360dce6b0ea69d0f4d1fdea4e1148291a13d0 (diff)
parent2059502c054f55e332aafe29c2476c5963033dc7 (diff)
Merge branch 'master' into plugins
Diffstat (limited to 'src')
-rw-r--r--src/bytestream-factory.c11
-rw-r--r--src/bytestream-factory.h3
-rw-r--r--src/capabilities.c2
-rw-r--r--src/capabilities.h2
-rw-r--r--src/connection-manager.c4
-rw-r--r--src/connection-manager.h2
-rw-r--r--src/connection.c407
-rw-r--r--src/connection.h5
-rw-r--r--src/ft-channel.c7
-rw-r--r--src/ft-manager.c51
-rw-r--r--src/gabble.c1
-rw-r--r--src/im-channel.c137
-rw-r--r--src/im-channel.h15
-rw-r--r--src/im-factory.c8
-rw-r--r--src/muc-factory.c3
-rw-r--r--src/muc-factory.h2
-rw-r--r--src/register.c3
-rw-r--r--src/register.h2
-rw-r--r--src/tube-dbus.c8
-rw-r--r--src/tube-stream.c4
-rw-r--r--src/util.c46
-rw-r--r--src/write-mgr-file.c5
22 files changed, 235 insertions, 493 deletions
diff --git a/src/bytestream-factory.c b/src/bytestream-factory.c
index 4336aa48c..728d2a414 100644
--- a/src/bytestream-factory.c
+++ b/src/bytestream-factory.c
@@ -297,8 +297,6 @@ disco_item_found_cb (GabbleDisco *disco,
send_proxy_query (self, item->jid, FALSE);
}
-static void query_socks5_proxies (GabbleBytestreamFactory *self);
-
static gboolean
socks5_proxies_timeout_cb (gpointer data)
{
@@ -316,13 +314,14 @@ socks5_proxies_timeout_cb (gpointer data)
return FALSE;
}
- query_socks5_proxies (self);
+ gabble_bytestream_factory_query_socks5_proxies (self);
return FALSE;
}
-static void
-query_socks5_proxies (GabbleBytestreamFactory *self)
+/* ask to the factory to try to find more proxies if needed */
+void
+gabble_bytestream_factory_query_socks5_proxies (GabbleBytestreamFactory *self)
{
GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (
self);
@@ -422,8 +421,6 @@ conn_status_changed_cb (GabbleConnection *conn,
priv->socks5_potential_proxies = randomize_g_slist (
priv->socks5_potential_proxies);
- query_socks5_proxies (self);
-
g_strfreev (jids);
}
}
diff --git a/src/bytestream-factory.h b/src/bytestream-factory.h
index dcc58fc53..ff5523de6 100644
--- a/src/bytestream-factory.h
+++ b/src/bytestream-factory.h
@@ -109,6 +109,9 @@ gchar *gabble_bytestream_factory_generate_stream_id (void);
GSList *gabble_bytestream_factory_get_socks5_proxies (
GabbleBytestreamFactory *self);
+void gabble_bytestream_factory_query_socks5_proxies (
+ GabbleBytestreamFactory *self);
+
G_END_DECLS
#endif /* #ifndef __BYTESTREAM_FACTORY_H__ */
diff --git a/src/capabilities.c b/src/capabilities.c
index 4b9f44a34..0a241cf40 100644
--- a/src/capabilities.c
+++ b/src/capabilities.c
@@ -63,7 +63,7 @@ static const Feature self_advertised_features[] =
{ FEATURE_FIXED, NS_IBB },
{ FEATURE_FIXED, NS_TUBES },
{ FEATURE_FIXED, NS_BYTESTREAMS },
- { FEATURE_FIXED, NS_FILE_TRANSFER },
+ { FEATURE_OPTIONAL, NS_FILE_TRANSFER },
{ FEATURE_OPTIONAL, NS_GOOGLE_TRANSPORT_P2P },
{ FEATURE_OPTIONAL, NS_JINGLE_TRANSPORT_ICEUDP },
diff --git a/src/capabilities.h b/src/capabilities.h
index 6b4266803..9a4cbfd3e 100644
--- a/src/capabilities.h
+++ b/src/capabilities.h
@@ -112,6 +112,8 @@ const GabbleCapabilitySet *gabble_capabilities_get_olpc_notify (void);
const GabbleCapabilitySet *gabble_capabilities_get_bundle_voice_v1 (void);
const GabbleCapabilitySet *gabble_capabilities_get_bundle_video_v1 (void);
+#define BUNDLE_PMUC_V1 "pmuc-v1"
+
/*
* capabilities_fill_cache
*
diff --git a/src/connection-manager.c b/src/connection-manager.c
index 5753b2714..9e798d0cd 100644
--- a/src/connection-manager.c
+++ b/src/connection-manager.c
@@ -126,7 +126,9 @@ static TpCMParamSpec jabber_params[] = {
/* FIXME: validate the JID according to the RFC */
tp_cm_param_filter_string_nonempty, NULL },
{ "password", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_REQUIRED | TP_CONN_MGR_PARAM_FLAG_REGISTER, NULL,
+ TP_CONN_MGR_PARAM_FLAG_REQUIRED | TP_CONN_MGR_PARAM_FLAG_REGISTER |
+ TP_CONN_MGR_PARAM_FLAG_SECRET,
+ NULL,
G_STRUCT_OFFSET(GabbleParams, password), NULL, NULL },
{ "server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
diff --git a/src/connection-manager.h b/src/connection-manager.h
index 4ef773511..89a5f50f4 100644
--- a/src/connection-manager.h
+++ b/src/connection-manager.h
@@ -36,8 +36,6 @@ struct _GabbleConnectionManagerClass {
struct _GabbleConnectionManager {
TpBaseConnectionManager parent;
-
- GabbleConnectionManagerPrivate *priv;
};
GType gabble_connection_manager_get_type (void);
diff --git a/src/connection.c b/src/connection.c
index d301d3dbf..1d91a4573 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -40,7 +40,6 @@
#include <telepathy-glib/handle-repo-dynamic.h>
#include <telepathy-glib/handle-repo-static.h>
#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-connection.h>
#include <telepathy-glib/svc-generic.h>
#include "extensions/extensions.h"
@@ -81,7 +80,6 @@ static guint disco_reply_timeout = 5;
#define DISCONNECT_TIMEOUT 5
-static void conn_service_iface_init (gpointer, gpointer);
static void capabilities_service_iface_init (gpointer, gpointer);
static void gabble_conn_contact_caps_iface_init (gpointer, gpointer);
static void conn_capabilities_fill_contact_attributes (GObject *obj,
@@ -92,8 +90,6 @@ static void conn_contact_capabilities_fill_contact_attributes (GObject *obj,
G_DEFINE_TYPE_WITH_CODE(GabbleConnection,
gabble_connection,
TP_TYPE_BASE_CONNECTION,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION,
- conn_service_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING,
conn_aliasing_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_AVATARS,
@@ -665,7 +661,7 @@ _gabble_connection_create_handle_repos (TpBaseConnection *conn,
gabble_normalize_contact, GUINT_TO_POINTER (GABBLE_JID_ANY));
repos[TP_HANDLE_TYPE_ROOM] =
tp_dynamic_handle_repo_new (TP_HANDLE_TYPE_ROOM, gabble_normalize_room,
- NULL);
+ conn);
repos[TP_HANDLE_TYPE_GROUP] =
tp_dynamic_handle_repo_new (TP_HANDLE_TYPE_GROUP, NULL, NULL);
repos[TP_HANDLE_TYPE_LIST] =
@@ -1970,6 +1966,7 @@ _gabble_connection_signal_own_presence (GabbleConnection *self, GError **error)
gboolean ret;
gchar *caps_hash;
gboolean voice_v1, video_v1;
+ GString *ext = g_string_new ("");
if (presence->status == GABBLE_PRESENCE_HIDDEN)
{
@@ -1995,27 +1992,19 @@ _gabble_connection_signal_own_presence (GabbleConnection *self, GError **error)
/* XEP-0115 deprecates 'ext' feature bundles. But we still need
* BUNDLE_VOICE_V1 it for backward-compatibility with Gabble 0.2 */
+ g_string_append (ext, BUNDLE_PMUC_V1);
+
voice_v1 = gabble_presence_has_cap (presence, NS_GOOGLE_FEAT_VOICE);
video_v1 = gabble_presence_has_cap (presence, NS_GOOGLE_FEAT_VIDEO);
- if (voice_v1 || video_v1)
- {
- GString *ext = g_string_new ("");
-
- if (voice_v1)
- g_string_append (ext, BUNDLE_VOICE_V1);
+ if (voice_v1)
+ g_string_append (ext, " " BUNDLE_VOICE_V1);
- if (video_v1)
- {
- if (ext->len > 0)
- g_string_append_c (ext, ' ');
- g_string_append (ext, BUNDLE_VIDEO_V1);
- }
+ if (video_v1)
+ g_string_append (ext, " " BUNDLE_VIDEO_V1);
- lm_message_node_set_attribute (node, "ext", ext->str);
-
- g_string_free (ext, TRUE);
- }
+ lm_message_node_set_attribute (node, "ext", ext->str);
+ g_string_free (ext, TRUE);
ret = _gabble_connection_send (self, message, error);
@@ -2256,15 +2245,19 @@ connection_iq_disco_cb (LmMessageHandler *handler,
features = gabble_capabilities_get_bundle_video_v1 ();
}
- if (features == NULL)
+ if (features == NULL && tp_strdiff (suffix, BUNDLE_PMUC_V1))
{
_gabble_connection_send_iq_error (self, message,
XMPP_ERROR_ITEM_NOT_FOUND, NULL);
}
else
{
- gabble_capability_set_foreach (features, add_feature_node,
- result_query);
+ /* Send an empty reply for a pmuc-v1 disco, matching Google's behaviour. */
+ if (features != NULL)
+ {
+ gabble_capability_set_foreach (features, add_feature_node,
+ result_query);
+ }
NODE_DEBUG (result_iq, "sending disco response");
@@ -3074,8 +3067,8 @@ _gabble_connection_find_conference_server (GabbleConnection *conn)
}
-static gchar *
-_gabble_connection_get_canonical_room_name (GabbleConnection *conn,
+gchar *
+gabble_connection_get_canonical_room_name (GabbleConnection *conn,
const gchar *name)
{
const gchar *server;
@@ -3093,355 +3086,6 @@ _gabble_connection_get_canonical_room_name (GabbleConnection *conn,
return gabble_encode_jid (name, server, NULL);
}
-
-typedef struct _RoomVerifyContext RoomVerifyContext;
-
-typedef struct {
- GabbleConnection *conn;
- DBusGMethodInvocation *invocation;
- gboolean errored;
- guint count;
- GArray *handles;
- RoomVerifyContext *contexts;
-} RoomVerifyBatch;
-
-struct _RoomVerifyContext {
- gchar *jid;
- guint index;
- RoomVerifyBatch *batch;
- GabbleDiscoRequest *request;
-};
-
-static void
-room_verify_batch_free (RoomVerifyBatch *batch)
-{
- TpBaseConnection *base = (TpBaseConnection *) (batch->conn);
- TpHandleRepoIface *room_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_ROOM);
- guint i;
-
- tp_handles_unref (room_handles, batch->handles);
- g_array_free (batch->handles, TRUE);
- for (i = 0; i < batch->count; i++)
- {
- g_free (batch->contexts[i].jid);
- }
- g_free (batch->contexts);
- g_slice_free (RoomVerifyBatch, batch);
-}
-
-/* Frees the error and the batch. */
-static void
-room_verify_batch_raise_error (RoomVerifyBatch *batch,
- GError *error)
-{
- guint i;
-
- dbus_g_method_return_error (batch->invocation, error);
- g_error_free (error);
- batch->errored = TRUE;
- for (i = 0; i < batch->count; i++)
- {
- if (batch->contexts[i].request)
- {
- gabble_disco_cancel_request (batch->conn->disco,
- batch->contexts[i].request);
- }
- }
- room_verify_batch_free (batch);
-}
-
-static RoomVerifyBatch *
-room_verify_batch_new (GabbleConnection *conn,
- DBusGMethodInvocation *invocation,
- guint count,
- const gchar **jids)
-{
- TpBaseConnection *base = (TpBaseConnection *) conn;
- TpHandleRepoIface *room_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_ROOM);
- RoomVerifyBatch *batch = g_slice_new (RoomVerifyBatch);
- guint i;
-
- batch->errored = FALSE;
- batch->conn = conn;
- batch->invocation = invocation;
- batch->count = count;
- batch->handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), count);
- batch->contexts = g_new0(RoomVerifyContext, count);
- for (i = 0; i < count; i++)
- {
- const gchar *name = jids[i];
- gchar *qualified_name;
- TpHandle handle;
-
- batch->contexts[i].index = i;
- batch->contexts[i].batch = batch;
-
- qualified_name = _gabble_connection_get_canonical_room_name (conn, name);
-
- if (!qualified_name)
- {
- GError *error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "requested room handle %s does not specify a server, but we "
- "have not discovered any local conference servers and no "
- "fallback was provided", name);
- DEBUG ("%s", error->message);
- room_verify_batch_raise_error (batch, error);
- return NULL;
- }
-
- batch->contexts[i].jid = qualified_name;
-
- /* has the handle been verified before? */
- handle = tp_handle_lookup (room_handles, qualified_name, NULL, NULL);
- if (handle)
- tp_handle_ref (room_handles, handle);
- g_array_append_val (batch->handles, handle);
- }
-
- return batch;
-}
-
-/* If all handles in the array have been disco'd or got from cache,
-free the batch and return TRUE. Else return FALSE. */
-static gboolean
-room_verify_batch_try_return (RoomVerifyBatch *batch)
-{
- guint i;
- TpHandleRepoIface *room_handles = tp_base_connection_get_handles (
- (TpBaseConnection *) batch->conn, TP_HANDLE_TYPE_ROOM);
- gchar *sender;
- GError *error = NULL;
-
- for (i = 0; i < batch->count; i++)
- {
- if (!g_array_index (batch->handles, TpHandle, i))
- {
- /* we're not ready yet */
- return FALSE;
- }
- }
-
- sender = dbus_g_method_get_sender (batch->invocation);
- if (!tp_handles_client_hold (room_handles, sender, batch->handles, &error))
- {
- g_assert (error != NULL);
- }
- g_free (sender);
-
- if (error == NULL)
- {
- tp_svc_connection_return_from_request_handles (batch->invocation,
- batch->handles);
- }
- else
- {
- dbus_g_method_return_error (batch->invocation, error);
- g_error_free (error);
- }
-
- room_verify_batch_free (batch);
- return TRUE;
-}
-
-static void
-room_jid_disco_cb (GabbleDisco *disco,
- GabbleDiscoRequest *request,
- const gchar *jid,
- const gchar *node,
- LmMessageNode *query_result,
- GError *error,
- gpointer user_data)
-{
- RoomVerifyContext *rvctx = user_data;
- RoomVerifyBatch *batch = rvctx->batch;
- TpHandleRepoIface *room_handles = tp_base_connection_get_handles (
- (TpBaseConnection *) batch->conn, TP_HANDLE_TYPE_ROOM);
- gboolean found = FALSE;
- TpHandle handle;
- NodeIter i;
-
- /* stop the request getting cancelled after it's already finished */
- rvctx->request = NULL;
-
- /* if an error is being handled already, quietly go away */
- if (batch->errored)
- {
- return;
- }
-
- if (error != NULL)
- {
- DEBUG ("disco reply error %s", error->message);
-
- /* disco will free the old error, _raise_error will free the new one */
- error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "can't retrieve room info: %s", error->message);
-
- room_verify_batch_raise_error (batch, error);
-
- return;
- }
-
- for (i = node_iter (query_result); i; i = node_iter_next (i))
- {
- LmMessageNode *lm_node = node_iter_data (i);
- const gchar *var;
-
- if (tp_strdiff (lm_node->name, "feature"))
- continue;
-
- var = lm_message_node_get_attribute (lm_node, "var");
-
- /* for servers who consider schema compliance to be an optional bonus */
- if (var == NULL)
- var = lm_message_node_get_attribute (lm_node, "type");
-
- if (!tp_strdiff (var, NS_MUC))
- {
- found = TRUE;
- break;
- }
- }
-
- if (!found)
- {
- DEBUG ("no MUC support for service name in jid %s", rvctx->jid);
-
- error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "specified server doesn't support MUC");
-
- room_verify_batch_raise_error (batch, error);
-
- return;
- }
-
- /* this refs the handle, so we're putting a ref in batch->handles */
- handle = tp_handle_ensure (room_handles, rvctx->jid, NULL, &error);
- if (handle == 0)
- {
- room_verify_batch_raise_error (batch, error);
- return;
- }
-
- DEBUG ("disco reported MUC support for service name in jid %s", rvctx->jid);
- g_array_index (batch->handles, TpHandle, rvctx->index) = handle;
-
- /* if this was the last callback to be run, send off the result */
- room_verify_batch_try_return (batch);
-}
-
-/**
- * room_jid_verify:
- *
- * Utility function that verifies that the service name of
- * the specified jid exists and reports MUC support.
- */
-static gboolean
-room_jid_verify (RoomVerifyBatch *batch,
- guint i,
- DBusGMethodInvocation *context)
-{
- gchar *room, *service;
- gboolean ret;
- GError *error = NULL;
-
- room = service = NULL;
-
- if (!gabble_decode_jid (batch->contexts[i].jid, &room, &service, NULL) ||
- room == NULL)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "unable to get room name and service from JID %s",
- batch->contexts[i].jid);
- ret = FALSE;
- goto out;
- }
-
- ret = (gabble_disco_request (batch->conn->disco, GABBLE_DISCO_TYPE_INFO,
- service, NULL, room_jid_disco_cb,
- batch->contexts + i,
- G_OBJECT (batch->conn), &error) != NULL);
-
-out:
- if (!ret)
- {
- room_verify_batch_raise_error (batch, error);
- }
-
- g_free (room);
- g_free (service);
-
- return ret;
-}
-
-
-/**
- * gabble_connection_request_handles
- *
- * Implements D-Bus method RequestHandles
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-static void
-gabble_connection_request_handles (TpSvcConnection *iface,
- guint handle_type,
- const gchar **names,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *) self;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- if (handle_type == TP_HANDLE_TYPE_ROOM)
- {
- RoomVerifyBatch *batch = NULL;
- guint count = 0, i;
- const gchar **cur_name;
-
- for (cur_name = names; *cur_name != NULL; cur_name++)
- {
- count++;
- }
-
- batch = room_verify_batch_new (self, context, count, names);
- if (!batch)
- {
- /* an error occurred while setting up the batch, and we returned
- error to dbus */
- return;
- }
-
- /* have all the handles been verified already? If so, nothing to do */
- if (room_verify_batch_try_return (batch))
- {
- return;
- }
-
- for (i = 0; i < count; i++)
- {
- if (!room_jid_verify (batch, i, context))
- {
- return;
- }
- }
-
- /* we've set the verification process going - the callback will handle
- returning or raising error */
- return;
- }
-
- /* else it's either an invalid type, or a type we can verify immediately -
- * in either case, let the superclass do it */
- tp_base_connection_dbus_request_handles (iface, handle_type, names, context);
-}
-
void
gabble_connection_ensure_capabilities (GabbleConnection *self,
const GabbleCapabilitySet *ensured)
@@ -3477,19 +3121,6 @@ gabble_connection_send_presence (GabbleConnection *conn,
return result;
}
-/* We reimplement RequestHandles to be able to do async validation on
- * room handles */
-static void
-conn_service_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcConnectionClass *klass = (TpSvcConnectionClass *) g_iface;
-
-#define IMPLEMENT(x) tp_svc_connection_implement_##x (klass, \
- gabble_connection_##x)
- IMPLEMENT(request_handles);
-#undef IMPLEMENT
-}
-
static void
capabilities_service_iface_init (gpointer g_iface, gpointer iface_data)
{
diff --git a/src/connection.h b/src/connection.h
index e15c25d6c..383393ee1 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -55,10 +55,9 @@ G_BEGIN_DECLS
"proxy.downtempo.de",\
"proxy.im.flosoft.biz",\
"proxy.jabber.bluendo.com", "proxy.jabber.dk", "proxy.jabber.freenet.de",\
- "proxy.fsinf.at", "proxy.jabber.minus273.org",\
+ "proxy.jabber.minus273.org",\
"proxy.jabber.planetteamspeak.com", "proxy.jabber.tf-network.de",\
"proxy.jabjab.de", "proxy.jabster.pl",\
- "proxy.schokokeks.org",\
"proxy.ubuntu-jabber.de", "proxy.ubuntu-jabber.net",\
"proxy65.unstable.nl", "proxy.verdammung.org", "proxy.vke.ru",\
"proxy.vodka-pomme.net", "proxy.jabbernet.eu",\
@@ -253,6 +252,8 @@ void _gabble_connection_send_iq_error (GabbleConnection *conn,
LmMessage *message, GabbleXmppError error, const gchar *errmsg);
const char *_gabble_connection_find_conference_server (GabbleConnection *);
+gchar *gabble_connection_get_canonical_room_name (GabbleConnection *conn,
+ const gchar *jid);
gboolean _gabble_connection_signal_own_presence (GabbleConnection *,
GError **);
diff --git a/src/ft-channel.c b/src/ft-channel.c
index 516238433..2450a0b9d 100644
--- a/src/ft-channel.c
+++ b/src/ft-channel.c
@@ -494,6 +494,13 @@ gabble_file_transfer_channel_constructor (GType type,
tp_handle_inspect (contact_repo, self->priv->initiator),
self->priv->filename, self->priv->size);
+ if (self->priv->initiator == base_conn->self_handle)
+ {
+ /* Outgoing FT , we'll need SOCK5 proxies when we'll offer the file */
+ gabble_bytestream_factory_query_socks5_proxies (
+ self->priv->connection->bytestream_factory);
+ }
+
return obj;
}
diff --git a/src/ft-manager.c b/src/ft-manager.c
index 87338a35c..5ab700227 100644
--- a/src/ft-manager.c
+++ b/src/ft-manager.c
@@ -545,8 +545,6 @@ void gabble_ft_manager_handle_si_request (GabbleFtManager *self,
{
GTimeVal val;
- g_time_val_from_iso8601 (date_str, &val);
-
/* FIXME: this assume the timezone is always UTC */
if (g_time_val_from_iso8601 (date_str, &val))
date = val.tv_sec;
@@ -601,16 +599,13 @@ gabble_ft_manager_get_tmp_dir (GabbleFtManager *self)
}
static void
-add_file_transfer_channel_class (GPtrArray *arr,
- TpHandle handle)
+add_file_transfer_channel_class (GPtrArray *arr)
{
GValue monster = {0, };
GHashTable *fixed_properties;
GValue *channel_type_value;
GValue *target_handle_type_value;
- g_assert (handle != 0);
-
g_value_init (&monster, TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS);
g_value_take_boxed (&monster,
dbus_g_type_specialized_construct (
@@ -641,19 +636,46 @@ add_file_transfer_channel_class (GPtrArray *arr,
}
static void
-gabble_ft_manager_get_contact_caps (GabbleCapsChannelManager *manager,
- TpHandle handle,
+gabble_ft_manager_get_contact_caps (
+ GabbleCapsChannelManager *manager G_GNUC_UNUSED,
+ TpHandle handle G_GNUC_UNUSED,
const GabbleCapabilitySet *caps,
GPtrArray *arr)
{
- GabbleFtManager *self = GABBLE_FT_MANAGER (manager);
+ if (gabble_capability_set_has (caps, NS_FILE_TRANSFER))
+ add_file_transfer_channel_class (arr);
+}
- g_assert (handle != 0);
+static void
+gabble_ft_manager_represent_client (
+ GabbleCapsChannelManager *manager G_GNUC_UNUSED,
+ const gchar *client_name,
+ const GPtrArray *filters,
+ const gchar * const *cap_tokens G_GNUC_UNUSED,
+ GabbleCapabilitySet *cap_set)
+{
+ guint i;
- /* We always support file transfer */
- if (handle == self->priv->connection->parent.self_handle ||
- gabble_capability_set_has (caps, NS_FILE_TRANSFER))
- add_file_transfer_channel_class (arr, handle);
+ for (i = 0; i < filters->len; i++)
+ {
+ GHashTable *channel_class = g_ptr_array_index (filters, i);
+
+ if (tp_strdiff (tp_asv_get_string (channel_class,
+ TP_IFACE_CHANNEL ".ChannelType"),
+ TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER))
+ continue;
+
+ if (tp_asv_get_uint32 (channel_class,
+ TP_IFACE_CHANNEL ".TargetHandleType", NULL)
+ != TP_HANDLE_TYPE_CONTACT)
+ continue;
+
+ DEBUG ("client %s supports file transfer", client_name);
+ gabble_capability_set_add (cap_set, NS_FILE_TRANSFER);
+ /* there's no point in looking at the subsequent filters if we've
+ * already added the FT capability */
+ break;
+ }
}
static void
@@ -663,4 +685,5 @@ caps_channel_manager_iface_init (gpointer g_iface,
GabbleCapsChannelManagerIface *iface = g_iface;
iface->get_contact_caps = gabble_ft_manager_get_contact_caps;
+ iface->represent_client = gabble_ft_manager_represent_client;
}
diff --git a/src/gabble.c b/src/gabble.c
index 992d12e08..18ce1ac51 100644
--- a/src/gabble.c
+++ b/src/gabble.c
@@ -144,6 +144,7 @@ gabble_main (int argc,
construct_cm, argc, argv);
#ifdef ENABLE_DEBUG
+ g_log_set_default_handler (g_log_default_handler, NULL);
g_object_unref (debug_sender);
#endif
diff --git a/src/im-channel.c b/src/im-channel.c
index 6db5e53f6..f4edc54cb 100644
--- a/src/im-channel.c
+++ b/src/im-channel.c
@@ -95,6 +95,12 @@ enum
/* private structure */
+typedef enum {
+ CHAT_STATES_UNKNOWN,
+ CHAT_STATES_SUPPORTED,
+ CHAT_STATES_NOT_SUPPORTED
+} ChatStateSupport;
+
struct _GabbleIMChannelPrivate
{
GabbleConnection *conn;
@@ -104,6 +110,7 @@ struct _GabbleIMChannelPrivate
gchar *peer_jid;
gboolean send_nick;
+ ChatStateSupport chat_states_supported;
/* FALSE unless at least one chat state notification has been sent; <gone/>
* will only be sent when the channel closes if this is TRUE. This prevents
@@ -172,6 +179,8 @@ gabble_im_channel_constructor (GType type, guint n_props,
else
priv->send_nick = TRUE;
+ priv->chat_states_supported = CHAT_STATES_UNKNOWN;
+
tp_message_mixin_init (obj, G_STRUCT_OFFSET (GabbleIMChannel, message_mixin),
conn);
@@ -394,20 +403,43 @@ gabble_im_channel_class_init (GabbleIMChannelClass *gabble_im_channel_class)
tp_message_mixin_init_dbus_properties (object_class);
}
+static gboolean
+chat_states_supported (GabbleIMChannel *self,
+ gboolean include_unknown)
+{
+ GabbleIMChannelPrivate *priv = self->priv;
+ GabblePresence *presence;
+
+ presence = gabble_presence_cache_get (priv->conn->presence_cache,
+ priv->handle);
+
+ if (presence != NULL && gabble_presence_has_cap (presence, NS_CHAT_STATES))
+ return TRUE;
+
+ switch (priv->chat_states_supported)
+ {
+ case CHAT_STATES_UNKNOWN:
+ return include_unknown;
+ case CHAT_STATES_SUPPORTED:
+ return TRUE;
+ case CHAT_STATES_NOT_SUPPORTED:
+ return FALSE;
+ default:
+ g_assert_not_reached ();
+ return FALSE;
+ }
+}
+
static void
emit_closed_and_send_gone (GabbleIMChannel *self)
{
GabbleIMChannelPrivate *priv = self->priv;
- GabblePresence *presence;
if (priv->send_gone)
{
- presence = gabble_presence_cache_get (priv->conn->presence_cache,
- priv->handle);
-
- if (presence && gabble_presence_has_cap (presence, NS_CHAT_STATES))
+ if (chat_states_supported (self, FALSE))
gabble_message_util_send_chat_state (G_OBJECT (self), priv->conn,
- LM_MESSAGE_SUB_TYPE_NORMAL, TP_CHANNEL_CHAT_STATE_GONE,
+ LM_MESSAGE_SUB_TYPE_CHAT, TP_CHANNEL_CHAT_STATE_GONE,
priv->peer_jid, NULL);
priv->send_gone = FALSE;
@@ -487,16 +519,12 @@ _gabble_im_channel_send_message (GObject *object,
{
GabbleIMChannel *self = GABBLE_IM_CHANNEL (object);
GabbleIMChannelPrivate *priv;
- GabblePresence *presence;
gint state = -1;
g_assert (GABBLE_IS_IM_CHANNEL (self));
priv = self->priv;
- presence = gabble_presence_cache_get (priv->conn->presence_cache,
- priv->handle);
-
- if (presence && gabble_presence_has_cap (presence, NS_CHAT_STATES))
+ if (chat_states_supported (self, TRUE))
{
state = TP_CHANNEL_CHAT_STATE_ACTIVE;
priv->send_gone = TRUE;
@@ -512,7 +540,6 @@ _gabble_im_channel_send_message (GObject *object,
priv->send_nick = FALSE;
}
-
/**
* _gabble_im_channel_receive
*
@@ -526,7 +553,8 @@ _gabble_im_channel_receive (GabbleIMChannel *chan,
const gchar *id,
const char *text,
TpChannelTextSendError send_error,
- TpDeliveryStatus delivery_status)
+ TpDeliveryStatus delivery_status,
+ gint state)
{
GabbleIMChannelPrivate *priv;
TpBaseConnection *base_conn;
@@ -545,6 +573,19 @@ _gabble_im_channel_receive (GabbleIMChannel *chan,
g_free (priv->peer_jid);
priv->peer_jid = g_strdup (from);
}
+
+ if (state == -1)
+ {
+ priv->chat_states_supported = CHAT_STATES_NOT_SUPPORTED;
+ }
+ else
+ {
+ priv->chat_states_supported = CHAT_STATES_SUPPORTED;
+
+ tp_svc_channel_interface_chat_state_emit_chat_state_changed (
+ (TpSvcChannelInterfaceChatState *) chan,
+ priv->handle, (TpChannelChatState) state);
+ }
}
else
{
@@ -553,6 +594,8 @@ _gabble_im_channel_receive (GabbleIMChannel *chan,
if (slash != NULL)
*slash = '\0';
+
+ priv->chat_states_supported = CHAT_STATES_UNKNOWN;
}
msg = tp_message_new (base_conn, 2, 2);
@@ -629,7 +672,7 @@ _gabble_im_channel_receive (GabbleIMChannel *chan,
void
_gabble_im_channel_state_receive (GabbleIMChannel *chan,
- guint state)
+ TpChannelChatState state)
{
GabbleIMChannelPrivate *priv;
@@ -637,6 +680,8 @@ _gabble_im_channel_state_receive (GabbleIMChannel *chan,
g_assert (GABBLE_IS_IM_CHANNEL (chan));
priv = chan->priv;
+ priv->chat_states_supported = CHAT_STATES_SUPPORTED;
+
tp_svc_channel_interface_chat_state_emit_chat_state_changed (
(TpSvcChannelInterfaceChatState *) chan,
priv->handle, state);
@@ -790,53 +835,47 @@ gabble_im_channel_set_chat_state (TpSvcChannelInterfaceChatState *iface,
{
GabbleIMChannel *self = GABBLE_IM_CHANNEL (iface);
GabbleIMChannelPrivate *priv;
- GabblePresence *presence;
GError *error = NULL;
g_assert (GABBLE_IS_IM_CHANNEL (self));
priv = self->priv;
- presence = gabble_presence_cache_get (priv->conn->presence_cache,
- priv->handle);
-
- if (presence && gabble_presence_has_cap (presence, NS_CHAT_STATES))
+ if (state >= NUM_TP_CHANNEL_CHAT_STATES)
{
- if (state >= NUM_TP_CHANNEL_CHAT_STATES)
- {
- DEBUG ("invalid state %u", state);
-
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "invalid state: %u", state);
- }
-
- if (state == TP_CHANNEL_CHAT_STATE_GONE)
- {
- /* We cannot explicitly set the Gone state */
- DEBUG ("you may not explicitly set the Gone state");
-
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "you may not explicitly set the Gone state");
- }
- else if (gabble_message_util_send_chat_state (G_OBJECT (self), priv->conn,
- LM_MESSAGE_SUB_TYPE_NORMAL, state, priv->peer_jid, &error))
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "invalid state: %u", state);
+ }
+ else if (state == TP_CHANNEL_CHAT_STATE_GONE)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "you may not explicitly set the Gone state");
+ }
+ /* Only send anything to the peer if we actually know they support chat
+ * states.
+ */
+ else if (chat_states_supported (self, FALSE))
+ {
+ if (gabble_message_util_send_chat_state (G_OBJECT (self), priv->conn,
+ LM_MESSAGE_SUB_TYPE_CHAT, state, priv->peer_jid, &error))
{
priv->send_gone = TRUE;
- }
-
- if (error != NULL)
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
+ /* Send the ChatStateChanged signal for the local user */
+ tp_svc_channel_interface_chat_state_emit_chat_state_changed (iface,
+ priv->conn->parent.self_handle, state);
}
-
- /* Send the ChatStateChanged signal for the local user */
- tp_svc_channel_interface_chat_state_emit_chat_state_changed (iface,
- priv->conn->parent.self_handle, state);
}
- tp_svc_channel_interface_chat_state_return_from_set_chat_state (context);
+ if (error != NULL)
+ {
+ DEBUG ("%s", error->message);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+ else
+ {
+ tp_svc_channel_interface_chat_state_return_from_set_chat_state (context);
+ }
}
static void
diff --git a/src/im-channel.h b/src/im-channel.h
index 7d7d96a14..2a2a2dc1e 100644
--- a/src/im-channel.h
+++ b/src/im-channel.h
@@ -66,10 +66,17 @@ GType gabble_im_channel_get_type (void);
GabbleIMChannelClass))
void _gabble_im_channel_receive (GabbleIMChannel *chan,
- TpChannelTextMessageType type, TpHandle sender, const char *from,
- time_t timestamp, const char *id, const char *text,
- TpChannelTextSendError send_error, TpDeliveryStatus delivery_status);
-void _gabble_im_channel_state_receive (GabbleIMChannel *chan, guint state);
+ TpChannelTextMessageType type,
+ TpHandle sender,
+ const char *from,
+ time_t timestamp,
+ const char *id,
+ const char *text,
+ TpChannelTextSendError send_error,
+ TpDeliveryStatus delivery_status,
+ gint state);
+void _gabble_im_channel_state_receive (GabbleIMChannel *chan,
+ TpChannelChatState state);
G_END_DECLS
diff --git a/src/im-factory.c b/src/im-factory.c
index 8f5cccca0..d2b12a112 100644
--- a/src/im-factory.c
+++ b/src/im-factory.c
@@ -283,12 +283,12 @@ im_factory_message_cb (LmMessageHandler *handler,
from, handle, msgtype, body);
}
- if (state != -1 && send_error == GABBLE_TEXT_CHANNEL_SEND_NO_ERROR)
- _gabble_im_channel_state_receive (chan, state);
-
if (body != NULL)
_gabble_im_channel_receive (chan, msgtype, handle, from, stamp, id, body,
- send_error, delivery_status);
+ send_error, delivery_status, state);
+ else if (state != -1 && send_error == GABBLE_TEXT_CHANNEL_SEND_NO_ERROR)
+ _gabble_im_channel_state_receive (chan, (TpChannelChatState) state);
+
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
diff --git a/src/muc-factory.c b/src/muc-factory.c
index 2caba4787..fd3b10d35 100644
--- a/src/muc-factory.c
+++ b/src/muc-factory.c
@@ -62,7 +62,6 @@ enum
LAST_PROPERTY
};
-typedef struct _GabbleMucFactoryPrivate GabbleMucFactoryPrivate;
struct _GabbleMucFactoryPrivate
{
GabbleConnection *conn;
@@ -105,6 +104,8 @@ gabble_muc_factory_init (GabbleMucFactory *fac)
{
GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
+ fac->priv = priv;
+
priv->text_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, g_object_unref);
priv->tubes_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
diff --git a/src/muc-factory.h b/src/muc-factory.h
index c17935ef4..8a5485bff 100644
--- a/src/muc-factory.h
+++ b/src/muc-factory.h
@@ -29,6 +29,7 @@ G_BEGIN_DECLS
typedef struct _GabbleMucFactory GabbleMucFactory;
typedef struct _GabbleMucFactoryClass GabbleMucFactoryClass;
+typedef struct _GabbleMucFactoryPrivate GabbleMucFactoryPrivate;
struct _GabbleMucFactoryClass {
GObjectClass parent_class;
@@ -36,6 +37,7 @@ struct _GabbleMucFactoryClass {
struct _GabbleMucFactory {
GObject parent;
+ GabbleMucFactoryPrivate *priv;
};
GType gabble_muc_factory_get_type (void);
diff --git a/src/register.c b/src/register.c
index aff4cb65b..9a9e0ff1b 100644
--- a/src/register.c
+++ b/src/register.c
@@ -60,7 +60,6 @@ enum
G_DEFINE_TYPE(GabbleRegister, gabble_register, G_TYPE_OBJECT);
/* private structure */
-typedef struct _GabbleRegisterPrivate GabbleRegisterPrivate;
struct _GabbleRegisterPrivate
{
GabbleConnection *conn;
@@ -75,6 +74,8 @@ struct _GabbleRegisterPrivate
static void
gabble_register_init (GabbleRegister *obj)
{
+ obj->priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_REGISTER,
+ GabbleRegisterPrivate);
}
static void gabble_register_set_property (GObject *object, guint property_id,
diff --git a/src/register.h b/src/register.h
index e38e52044..f4ea593d4 100644
--- a/src/register.h
+++ b/src/register.h
@@ -33,6 +33,7 @@ G_BEGIN_DECLS
typedef struct _GabbleRegister GabbleRegister;
typedef struct _GabbleRegisterClass GabbleRegisterClass;
+typedef struct _GabbleRegisterPrivate GabbleRegisterPrivate;
GType gabble_register_get_type (void);
@@ -57,6 +58,7 @@ struct _GabbleRegisterClass {
struct _GabbleRegister {
GObject parent;
+ GabbleRegisterPrivate *priv;
};
GabbleRegister *gabble_register_new (GabbleConnection *conn);
diff --git a/src/tube-dbus.c b/src/tube-dbus.c
index 9db9f1968..bb4961840 100644
--- a/src/tube-dbus.c
+++ b/src/tube-dbus.c
@@ -955,6 +955,14 @@ gabble_tube_dbus_constructor (GType type,
priv->reassembly_bytes_needed = 0;
g_assert (priv->muc == NULL);
+
+ if (priv->requested)
+ {
+ /* We created this outgoing 1-1 D-Bus tube and so will need SOCKS5
+ * proxies when we'll offer it. */
+ gabble_bytestream_factory_query_socks5_proxies (
+ priv->conn->bytestream_factory);
+ }
}
/* Tube needs to be offered if we initiated AND requested it. Being
diff --git a/src/tube-stream.c b/src/tube-stream.c
index 9aedd5f98..de9bf4fb0 100644
--- a/src/tube-stream.c
+++ b/src/tube-stream.c
@@ -1516,6 +1516,10 @@ gabble_tube_stream_constructor (GType type,
else
{
priv->state = TP_TUBE_CHANNEL_STATE_LOCAL_PENDING;
+
+ /* We'll need SOCKS5 proxies if the tube is accepted */
+ gabble_bytestream_factory_query_socks5_proxies (
+ priv->conn->bytestream_factory);
}
if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
diff --git a/src/util.c b/src/util.c
index d22844d42..351bacda1 100644
--- a/src/util.c
+++ b/src/util.c
@@ -415,35 +415,47 @@ gabble_normalize_room (TpHandleRepoIface *repo,
gpointer context,
GError **error)
{
- char *at = strchr (jid, '@');
- char *slash = strchr (jid, '/');
+ GabbleConnection *conn;
+ gchar *qualified_name, *resource;
- /* there'd better be an @ somewhere after the first character */
- if (at == NULL)
+ /* Only look up the canonical room name if we got a GabbleConnection.
+ * This should only happen in the test-handles test. */
+ if (context != NULL)
{
- INVALID_HANDLE (error,
- "invalid room JID %s: does not contain '@'", jid);
- return NULL;
+ conn = GABBLE_CONNECTION (context);
+ qualified_name = gabble_connection_get_canonical_room_name (conn, jid);
+
+ if (qualified_name == NULL)
+ {
+ INVALID_HANDLE (error,
+ "requested room handle %s does not specify a server, but we "
+ "have not discovered any local conference servers and no "
+ "fallback was provided", jid);
+ return NULL;
+ }
}
- if (at == jid)
+ else
{
- INVALID_HANDLE (error,
- "invalid room JID %s: room name before '@' may not be empty", jid);
+ qualified_name = g_strdup (jid);
+ }
+
+ if (!gabble_decode_jid (qualified_name, NULL, NULL, &resource))
+ {
+ INVALID_HANDLE (error, "room JID %s is invalid", qualified_name);
return NULL;
}
- /* room names can't contain the nick part */
- if (slash != NULL)
+ if (resource != NULL)
{
INVALID_HANDLE (error,
- "invalid room JID %s: contains nickname part after '/' too", jid);
+ "invalid room JID %s: contains nickname part after '/' too",
+ qualified_name);
+ g_free (qualified_name);
+ g_free (resource);
return NULL;
}
- /* the room and service parts are both case-insensitive, so lowercase
- * them both; gabble_decode_jid is overkill here
- */
- return g_utf8_strdown (jid, -1);
+ return qualified_name;
}
gchar *
diff --git a/src/write-mgr-file.c b/src/write-mgr-file.c
index a5c9cd905..8a26a50c9 100644
--- a/src/write-mgr-file.c
+++ b/src/write-mgr-file.c
@@ -48,9 +48,10 @@ mgr_file_contents (const char *busname,
for (row = protocol->parameters; row->name; row++)
{
gchar *param_name = g_strdup_printf ("param-%s", row->name);
- gchar *param_value = g_strdup_printf ("%s%s%s", row->dtype,
+ gchar *param_value = g_strdup_printf ("%s%s%s%s", row->dtype,
(row->flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED ? " required" : ""),
- (row->flags & TP_CONN_MGR_PARAM_FLAG_REGISTER ? " register" : ""));
+ (row->flags & TP_CONN_MGR_PARAM_FLAG_REGISTER ? " register" : ""),
+ (row->flags & TP_CONN_MGR_PARAM_FLAG_SECRET ? " secret" : ""));
g_key_file_set_string (f, section_name, param_name, param_value);
g_free (param_value);
g_free (param_name);