~ken-vandine/ubuntu/precise/telepathy-gabble/ubuntu

« back to all changes in this revision

Viewing changes to src/connection.c

  • Committer: Ken VanDine
  • Date: 2012-02-22 19:53:58 UTC
  • mfrom: (1.7.11)
  • Revision ID: ken.vandine@canonical.com-20120222195358-yzb8u3oy48rzcdtj
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 */
20
20
 
21
 
#include "config.h"
22
21
#include "connection.h"
23
22
#include "gabble.h"
24
23
 
28
27
#include <dbus/dbus-glib.h>
29
28
#include <dbus/dbus-glib-lowlevel.h>
30
29
#include <glib-object.h>
31
 
#include <loudmouth/loudmouth.h>
32
 
#include <wocky/wocky-connector.h>
33
 
#include <wocky/wocky-disco-identity.h>
34
 
#include <wocky/wocky-tls-handler.h>
35
 
#include <wocky/wocky-ping.h>
36
 
#include <wocky/wocky-utils.h>
37
 
#include <wocky/wocky-xmpp-error.h>
38
 
#include <wocky/wocky-data-form.h>
 
30
#include <wocky/wocky.h>
39
31
#include <telepathy-glib/channel-manager.h>
40
32
#include <telepathy-glib/dbus.h>
41
33
#include <telepathy-glib/enums.h>
49
41
 
50
42
#define DEBUG_FLAG GABBLE_DEBUG_CONNECTION
51
43
 
 
44
#include <gabble/error.h>
52
45
#include "bytestream-factory.h"
53
46
#include "gabble/capabilities.h"
54
47
#include "gabble/caps-channel-manager.h"
 
48
#include "gabble/plugin-connection.h"
55
49
#include "caps-hash.h"
56
50
#include "auth-manager.h"
57
51
#include "conn-aliasing.h"
98
92
  const GArray *contacts, GHashTable *attributes_hash);
99
93
static void conn_contact_capabilities_fill_contact_attributes (GObject *obj,
100
94
  const GArray *contacts, GHashTable *attributes_hash);
 
95
static void gabble_plugin_connection_iface_init (
 
96
    GabblePluginConnectionInterface *iface,
 
97
    gpointer conn);
 
98
static gchar *_gabble_plugin_connection_get_full_jid (
 
99
    GabblePluginConnection *conn);
 
100
static TpBaseContactList *_gabble_plugin_connection_get_contact_list (
 
101
    GabblePluginConnection *conn);
101
102
 
102
103
G_DEFINE_TYPE_WITH_CODE(GabbleConnection,
103
104
    gabble_connection,
143
144
      conn_power_saving_iface_init);
144
145
    G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_CONNECTION_INTERFACE_ADDRESSING,
145
146
      conn_addressing_iface_init);
 
147
    G_IMPLEMENT_INTERFACE (GABBLE_TYPE_PLUGIN_CONNECTION,
 
148
      gabble_plugin_connection_iface_init);
146
149
    )
147
150
 
148
151
/* properties */
288
291
   * to connected */
289
292
  guint waiting_connected;
290
293
 
 
294
  /* Used to cancel pending calls to _gabble_connection_send_with_reply(). It
 
295
   * should not be necessary because by the time we get to cancelling this (in
 
296
   * our dispose()) the porter should be long dead and have called back for all
 
297
   * outstanding requests. However... call this paranoia, and a desire to
 
298
   * delete the Loudmouth compatibility layer without spending any more hours
 
299
   * untangling even more old code.
 
300
   */
 
301
  GCancellable *iq_reply_cancellable;
 
302
 
291
303
  gboolean closing;
292
304
  /* gobject housekeeping */
293
305
  gboolean dispose_has_run;
294
306
};
295
307
 
296
 
static guint sig_id_porter_available = 0;
297
 
 
298
308
static void connection_capabilities_update_cb (GabblePresenceCache *cache,
299
309
    TpHandle handle,
300
310
    const GabbleCapabilitySet *old_cap_set,
315
325
_gabble_connection_create_channel_managers (TpBaseConnection *conn)
316
326
{
317
327
  GabbleConnection *self = GABBLE_CONNECTION (conn);
 
328
  GabblePluginConnection *plugin_connection = GABBLE_PLUGIN_CONNECTION (self);
318
329
  GPtrArray *channel_managers = g_ptr_array_sized_new (5);
319
330
  GabblePluginLoader *loader;
320
331
  GPtrArray *tmp;
365
376
        "connection", self,
366
377
        NULL));
367
378
 
 
379
#ifdef ENABLE_FILE_TRANSFER
368
380
  self->ft_manager = gabble_ft_manager_new (self);
369
381
  g_ptr_array_add (channel_managers, self->ft_manager);
 
382
#endif
370
383
 
371
384
  /* plugin channel managers */
372
385
  loader = gabble_plugin_loader_dup ();
373
 
  tmp = gabble_plugin_loader_create_channel_managers (loader, conn);
 
386
  tmp = gabble_plugin_loader_create_channel_managers (loader,
 
387
      plugin_connection);
374
388
  g_object_unref (loader);
375
389
 
376
390
  g_ptr_array_foreach (tmp, add_to_array, channel_managers);
379
393
  return channel_managers;
380
394
}
381
395
 
 
396
static void
 
397
gabble_plugin_connection_iface_init (
 
398
    GabblePluginConnectionInterface *iface,
 
399
    gpointer conn)
 
400
{
 
401
  iface->add_sidecar_own_caps = gabble_connection_add_sidecar_own_caps;
 
402
  iface->add_sidecar_own_caps_full=
 
403
    gabble_connection_add_sidecar_own_caps_full;
 
404
  iface->get_session = gabble_connection_get_session;
 
405
  iface->get_full_jid = _gabble_plugin_connection_get_full_jid;
 
406
  iface->get_jid_for_caps = gabble_connection_get_jid_for_caps;
 
407
  iface->pick_best_resource_for_caps =
 
408
    gabble_connection_pick_best_resource_for_caps;
 
409
  iface->get_contact_list = _gabble_plugin_connection_get_contact_list;
 
410
  iface->get_caps = gabble_connection_get_caps;
 
411
}
 
412
 
382
413
static GObject *
383
414
gabble_connection_constructor (GType type,
384
415
                               guint n_construct_properties,
531
562
    }
532
563
 
533
564
  self->priv = priv;
534
 
  self->lmconn = lm_connection_new ();
 
565
  priv->iq_reply_cancellable = g_cancellable_new ();
535
566
 
536
567
  priv->caps_serial = 1;
537
568
  priv->last_activity_time = time (NULL);
1163
1194
          FALSE,
1164
1195
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1165
1196
 
1166
 
  /**
1167
 
   * @self: a connection
1168
 
   * @porter: a porter
1169
 
   *
1170
 
   * Emitted when the WockyPorter becomes available.
1171
 
   */
1172
 
  sig_id_porter_available = g_signal_new ("porter-available",
1173
 
      G_OBJECT_CLASS_TYPE (gabble_connection_class),
1174
 
      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL,
1175
 
      g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, WOCKY_TYPE_PORTER);
1176
 
 
1177
1197
  gabble_connection_class->properties_class.interfaces = prop_interfaces;
1178
1198
  tp_dbus_properties_mixin_class_init (object_class,
1179
1199
      G_STRUCT_OFFSET (GabbleConnectionClass, properties_class));
1233
1253
  tp_clear_object (&priv->connector);
1234
1254
  tp_clear_object (&self->session);
1235
1255
 
1236
 
  /* ownership of our porter was transferred to the LmConnection */
 
1256
  /* The porter was borrowed from the session. */
1237
1257
  priv->porter = NULL;
1238
 
  tp_clear_pointer (&self->lmconn, lm_connection_unref);
 
1258
  /* Cancel any outstanding _gabble_connection_send_with_reply() requests. */
 
1259
  g_cancellable_cancel (priv->iq_reply_cancellable);
 
1260
  tp_clear_object (&priv->iq_reply_cancellable);
1239
1261
 
1240
1262
  g_hash_table_unref (priv->client_caps);
1241
1263
  gabble_capability_set_free (priv->all_caps);
1366
1388
  return g_strconcat (bare_jid, "/", conn->priv->resource, NULL);
1367
1389
}
1368
1390
 
 
1391
static gchar *
 
1392
_gabble_plugin_connection_get_full_jid (GabblePluginConnection *plugin_conn)
 
1393
{
 
1394
  GabbleConnection *conn = GABBLE_CONNECTION (plugin_conn);
 
1395
  return gabble_connection_get_full_jid (conn);
 
1396
}
 
1397
 
1369
1398
/**
1370
1399
 * gabble_connection_dup_porter:
1371
1400
 *
1387
1416
}
1388
1417
 
1389
1418
WockySession *
1390
 
gabble_connection_get_session (GabbleConnection *connection)
 
1419
gabble_connection_get_session (GabblePluginConnection *plugin_connection)
1391
1420
{
 
1421
  GabbleConnection *connection = GABBLE_CONNECTION (plugin_connection);
 
1422
 
1392
1423
  g_return_val_if_fail (GABBLE_IS_CONNECTION (connection), NULL);
1393
1424
 
1394
1425
  return connection->session;
1397
1428
/**
1398
1429
 * _gabble_connection_send
1399
1430
 *
1400
 
 * Send an LmMessage and trap network errors appropriately.
 
1431
 * Send an WockyStanza and trap network errors appropriately.
1401
1432
 */
1402
1433
gboolean
1403
 
_gabble_connection_send (GabbleConnection *conn, LmMessage *msg, GError **error)
 
1434
_gabble_connection_send (GabbleConnection *conn, WockyStanza *msg, GError **error)
1404
1435
{
1405
1436
  g_assert (GABBLE_IS_CONNECTION (conn));
1406
1437
 
1407
 
  if (conn->lmconn == NULL || conn->priv->porter == NULL)
 
1438
  if (conn->priv->porter == NULL)
1408
1439
    {
1409
1440
      g_set_error_literal (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
1410
1441
              "connection is disconnected");
1431
1462
    GabbleConnectionMsgReplyFunc reply_func;
1432
1463
 
1433
1464
    GabbleConnection *conn;
1434
 
    LmMessage *sent_msg;
 
1465
    WockyStanza *sent_msg;
1435
1466
    gpointer user_data;
1436
1467
 
1437
1468
    GObject *object;
1438
1469
    gboolean object_alive;
1439
1470
} GabbleMsgHandlerData;
1440
1471
 
1441
 
static LmHandlerResult
1442
 
message_send_reply_cb (LmMessageHandler *handler,
1443
 
                       LmConnection *connection,
1444
 
                       LmMessage *reply_msg,
1445
 
                       gpointer user_data)
1446
 
{
1447
 
  GabbleMsgHandlerData *handler_data = user_data;
1448
 
  LmMessageSubType sub_type;
1449
 
 
1450
 
  sub_type = lm_message_get_sub_type (reply_msg);
1451
 
 
1452
 
  /* Is it a reply to this message? If we're talking to another loudmouth,
1453
 
   * they can send us messages which have the same ID as ones we send. :-O */
1454
 
  if (sub_type != LM_MESSAGE_SUB_TYPE_RESULT &&
1455
 
      sub_type != LM_MESSAGE_SUB_TYPE_ERROR)
1456
 
    {
1457
 
      return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
1458
 
    }
1459
 
 
1460
 
  if (handler_data->object_alive && handler_data->reply_func != NULL)
1461
 
    {
1462
 
      return handler_data->reply_func (handler_data->conn,
1463
 
                                       handler_data->sent_msg,
1464
 
                                       reply_msg,
1465
 
                                       handler_data->object,
1466
 
                                       handler_data->user_data);
1467
 
    }
1468
 
 
1469
 
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
1470
 
}
1471
 
 
1472
1472
static void
1473
1473
message_send_object_destroy_notify_cb (gpointer data,
1474
1474
                                       GObject *where_the_object_was)
1480
1480
}
1481
1481
 
1482
1482
static void
1483
 
message_send_handler_destroy_cb (gpointer data)
 
1483
msg_handler_data_free (GabbleMsgHandlerData *handler_data)
1484
1484
{
1485
 
  GabbleMsgHandlerData *handler_data = data;
1486
 
 
1487
 
  lm_message_unref (handler_data->sent_msg);
 
1485
  g_object_unref (handler_data->sent_msg);
1488
1486
 
1489
1487
  if (handler_data->object != NULL)
1490
1488
    {
1496
1494
  g_slice_free (GabbleMsgHandlerData, handler_data);
1497
1495
}
1498
1496
 
 
1497
static void
 
1498
message_send_reply_cb (
 
1499
    GObject *source,
 
1500
    GAsyncResult *result,
 
1501
    gpointer user_data)
 
1502
{
 
1503
  GabbleMsgHandlerData *handler_data = user_data;
 
1504
 
 
1505
  if (handler_data->object_alive && handler_data->reply_func != NULL)
 
1506
    {
 
1507
      WockyPorter *porter = WOCKY_PORTER (source);
 
1508
      GError *error = NULL;
 
1509
      WockyStanza *stanza = wocky_porter_send_iq_finish (porter, result, &error);
 
1510
 
 
1511
      if (stanza != NULL)
 
1512
        {
 
1513
          handler_data->reply_func (handler_data->conn,
 
1514
                                    handler_data->sent_msg,
 
1515
                                    stanza,
 
1516
                                    handler_data->object,
 
1517
                                    handler_data->user_data);
 
1518
          g_object_unref (stanza);
 
1519
        }
 
1520
      else
 
1521
        {
 
1522
          DEBUG ("send_iq_async failed: %s", error->message);
 
1523
          g_error_free (error);
 
1524
        }
 
1525
    }
 
1526
 
 
1527
  msg_handler_data_free (handler_data);
 
1528
}
 
1529
 
1499
1530
/**
1500
1531
 * _gabble_connection_send_with_reply
1501
1532
 *
1502
 
 * Send a tracked LmMessage and trap network errors appropriately.
 
1533
 * Send a tracked WockyStanza and trap network errors appropriately.
1503
1534
 *
1504
1535
 * If object is non-NULL the handler will follow the lifetime of that object,
1505
1536
 * which means that if the object is destroyed the callback will not be invoked.
1506
1537
 *
1507
 
 * if reply_func is NULL the reply will be ignored but connection_iq_unknown_cb
1508
 
 * won't be called.
 
1538
 * if reply_func is NULL the reply will be ignored.
1509
1539
 */
1510
1540
gboolean
1511
1541
_gabble_connection_send_with_reply (GabbleConnection *conn,
1512
 
                                    LmMessage *msg,
 
1542
                                    WockyStanza *msg,
1513
1543
                                    GabbleConnectionMsgReplyFunc reply_func,
1514
1544
                                    GObject *object,
1515
1545
                                    gpointer user_data,
1516
1546
                                    GError **error)
1517
1547
{
1518
 
  LmMessageHandler *handler;
 
1548
  GabbleConnectionPrivate *priv;
1519
1549
  GabbleMsgHandlerData *handler_data;
1520
 
  gboolean ret;
1521
 
  GError *lmerror = NULL;
1522
1550
 
1523
1551
  g_assert (GABBLE_IS_CONNECTION (conn));
 
1552
  priv = conn->priv;
1524
1553
 
1525
 
  if (conn->lmconn == NULL)
 
1554
  if (priv->porter == NULL)
1526
1555
    {
1527
1556
      g_set_error_literal (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
1528
1557
              "connection is disconnected");
1529
1558
      return FALSE;
1530
1559
    }
1531
1560
 
1532
 
  lm_message_ref (msg);
 
1561
  g_object_ref (msg);
1533
1562
 
1534
1563
  handler_data = g_slice_new (GabbleMsgHandlerData);
1535
1564
  handler_data->reply_func = reply_func;
1546
1575
                         handler_data);
1547
1576
    }
1548
1577
 
1549
 
  handler = lm_message_handler_new (message_send_reply_cb, handler_data,
1550
 
                                    message_send_handler_destroy_cb);
1551
 
 
1552
 
  ret = lm_connection_send_with_reply (conn->lmconn, msg, handler, &lmerror);
1553
 
  if (!ret)
1554
 
    {
1555
 
      DEBUG ("failed: %s", lmerror->message);
1556
 
 
1557
 
      if (error)
1558
 
        {
1559
 
          g_set_error (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
1560
 
              "message send failed: %s", lmerror->message);
1561
 
        }
1562
 
 
1563
 
      g_error_free (lmerror);
1564
 
    }
1565
 
 
1566
 
  lm_message_handler_unref (handler);
1567
 
 
1568
 
  return ret;
 
1578
  wocky_porter_send_iq_async (priv->porter, msg,
 
1579
      priv->iq_reply_cancellable, message_send_reply_cb, handler_data);
 
1580
 
 
1581
  return TRUE;
1569
1582
}
1570
1583
 
1571
1584
static void connect_iq_callbacks (GabbleConnection *conn);
1572
1585
static gboolean iq_disco_cb (WockyPorter *, WockyStanza *, gpointer);
1573
1586
static gboolean iq_version_cb (WockyPorter *, WockyStanza *, gpointer);
1574
 
static gboolean iq_unknown_cb (WockyPorter *, WockyStanza *, gpointer);
1575
1587
static void connection_disco_cb (GabbleDisco *, GabbleDiscoRequest *,
1576
 
    const gchar *, const gchar *, LmMessageNode *, GError *, gpointer);
 
1588
    const gchar *, const gchar *, WockyNode *, GError *, gpointer);
1577
1589
static void decrement_waiting_connected (GabbleConnection *connection);
1578
1590
static void connection_initial_presence_cb (GObject *, GAsyncResult *,
1579
1591
    gpointer);
1722
1734
    GabbleDiscoRequest *request,
1723
1735
    const gchar *jid,
1724
1736
    const gchar *node,
1725
 
    LmMessageNode *result,
 
1737
    WockyNode *result,
1726
1738
    GError *disco_error,
1727
1739
    gpointer user_data)
1728
1740
{
1729
1741
  GabbleConnection *conn = user_data;
1730
 
  NodeIter i;
1731
1742
 
1732
1743
  if (disco_error != NULL)
1733
1744
    {
1735
1746
    }
1736
1747
  else
1737
1748
    {
1738
 
      for (i = node_iter (result); i; i = node_iter_next (i))
 
1749
      WockyNodeIter i;
 
1750
      WockyNode *child;
 
1751
 
 
1752
      wocky_node_iter_init (&i, result, "identity", NULL);
 
1753
      while (wocky_node_iter_next (&i, &child))
1739
1754
        {
1740
 
          LmMessageNode *child = node_iter_data (i);
 
1755
          const gchar *category = wocky_node_get_attribute (child,
 
1756
              "category");
 
1757
          const gchar *type = wocky_node_get_attribute (child, "type");
1741
1758
 
1742
 
          if (!tp_strdiff (child->name, "identity"))
 
1759
          if (!tp_strdiff (category, "pubsub") &&
 
1760
              !tp_strdiff (type, "pep"))
1743
1761
            {
1744
 
              const gchar *category = lm_message_node_get_attribute (child,
1745
 
                  "category");
1746
 
              const gchar *type = lm_message_node_get_attribute (child, "type");
1747
 
 
1748
 
              if (!tp_strdiff (category, "pubsub") &&
1749
 
                  !tp_strdiff (type, "pep"))
1750
 
                {
1751
 
                  DEBUG ("Server advertises PEP support in our jid features");
1752
 
                  conn->features |= GABBLE_CONNECTION_FEATURES_PEP;
1753
 
                }
 
1762
              DEBUG ("Server advertises PEP support in our jid features");
 
1763
              conn->features |= GABBLE_CONNECTION_FEATURES_PEP;
1754
1764
            }
1755
1765
        }
1756
1766
    }
1885
1895
  g_signal_connect (priv->porter, "remote-error",
1886
1896
      G_CALLBACK (remote_error_cb), self);
1887
1897
 
1888
 
  lm_connection_set_porter (self->lmconn, priv->porter);
1889
 
  g_signal_emit (self, sig_id_porter_available, 0, priv->porter);
 
1898
  g_signal_emit_by_name (self, "porter-available", priv->porter);
1890
1899
  connect_iq_callbacks (self);
1891
1900
 
1892
1901
  wocky_pep_service_start (self->pep_location, self->session);
2078
2087
      WOCKY_PORTER_HANDLER_PRIORITY_NORMAL,
2079
2088
      connection_iq_last_cb, conn,
2080
2089
      '(', "query", ':', NS_LAST, ')', NULL);
2081
 
 
2082
 
  /* FIXME: the porter should do this for us. */
2083
 
  wocky_porter_register_handler_from_anyone (priv->porter,
2084
 
      WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE,
2085
 
      WOCKY_PORTER_HANDLER_PRIORITY_MIN,
2086
 
      iq_unknown_cb, conn, NULL);
2087
2090
}
2088
2091
 
2089
2092
/**
2314
2317
 
2315
2318
void
2316
2319
gabble_connection_fill_in_caps (GabbleConnection *self,
2317
 
    LmMessage *presence_message)
 
2320
    WockyStanza *presence_message)
2318
2321
{
2319
2322
  GabblePresence *presence = self->self_presence;
2320
 
  LmMessageNode *node = lm_message_get_node (presence_message);
 
2323
  WockyNode *node = wocky_stanza_get_top_node (presence_message);
2321
2324
  gchar *caps_hash;
2322
2325
  gboolean share_v1, voice_v1, video_v1;
2323
2326
  GString *ext = g_string_new ("");
2324
2327
 
2325
2328
  /* XEP-0115 version 1.5 uses a verification string in the 'ver' attribute */
2326
2329
  caps_hash = caps_hash_compute_from_self_presence (self);
2327
 
  node = lm_message_node_add_child (node, "c", NULL);
2328
 
  lm_message_node_set_attributes (
 
2330
  node = wocky_node_add_child_with_content (node, "c", NULL);
 
2331
  wocky_node_set_attributes (
2329
2332
    node,
2330
 
    "xmlns", NS_CAPS,
2331
2333
    "hash",  "sha-1",
2332
2334
    "node",  NS_GABBLE_CAPS,
2333
2335
    "ver",   caps_hash,
2334
2336
    NULL);
 
2337
  node->ns = g_quark_from_string (NS_CAPS);
2335
2338
 
2336
2339
  /* Ensure this set of capabilities is in the cache. */
2337
2340
  gabble_presence_cache_add_own_caps (self->presence_cache, caps_hash,
2358
2361
    g_string_append (ext, " " BUNDLE_CAMERA_V1);
2359
2362
  }
2360
2363
 
2361
 
  lm_message_node_set_attribute (node, "ext", ext->str);
 
2364
  wocky_node_set_attribute (node, "ext", ext->str);
2362
2365
  g_string_free (ext, TRUE);
2363
2366
  g_free (caps_hash);
2364
2367
}
2370
2373
{
2371
2374
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
2372
2375
      (TpBaseConnection *) self, TP_HANDLE_TYPE_CONTACT);
2373
 
  LmMessage *message;
 
2376
  WockyStanza *message;
2374
2377
  gboolean ret;
2375
2378
  TpHandle handle;
2376
2379
 
2385
2388
    }
2386
2389
 
2387
2390
  /* We deliberately don't include anything except the caps here */
2388
 
  message = lm_message_new_with_sub_type (recipient, LM_MESSAGE_TYPE_PRESENCE,
2389
 
      LM_MESSAGE_SUB_TYPE_AVAILABLE);
 
2391
  message = wocky_stanza_build (
 
2392
      WOCKY_STANZA_TYPE_PRESENCE, WOCKY_STANZA_SUB_TYPE_AVAILABLE,
 
2393
      NULL, recipient,
 
2394
      NULL);
2390
2395
 
2391
2396
  gabble_connection_fill_in_caps (self, message);
2392
2397
 
2393
2398
  ret = _gabble_connection_send (self, message, error);
2394
2399
 
2395
 
  lm_message_unref (message);
 
2400
  g_object_unref (message);
2396
2401
 
2397
2402
  return ret;
2398
2403
}
2404
2409
    GError **error)
2405
2410
{
2406
2411
  GabblePresence *presence = self->self_presence;
2407
 
  LmMessage *message = gabble_presence_as_message (presence, to);
2408
 
  LmMessageNode *decloak;
 
2412
  WockyStanza *message = gabble_presence_as_message (presence, to);
 
2413
  WockyNode *decloak;
2409
2414
  gboolean ret;
2410
2415
 
2411
2416
  gabble_connection_fill_in_caps (self, message);
2412
2417
 
2413
 
  decloak = lm_message_node_add_child (lm_message_get_node (message),
 
2418
  decloak = wocky_node_add_child_with_content (wocky_stanza_get_top_node (message),
2414
2419
      "temppres", NULL);
2415
 
  lm_message_node_set_attribute (decloak, "xmlns", NS_TEMPPRES);
 
2420
  decloak->ns = g_quark_from_string (NS_TEMPPRES);
2416
2421
 
2417
2422
  if (reason != NULL && *reason != '\0')
2418
2423
    {
2419
 
      lm_message_node_set_attribute (decloak, "reason", reason);
 
2424
      wocky_node_set_attribute (decloak, "reason", reason);
2420
2425
    }
2421
2426
 
2422
2427
  ret = _gabble_connection_send (self, message, error);
2423
 
  lm_message_unref (message);
 
2428
  g_object_unref (message);
2424
2429
 
2425
2430
  return ret;
2426
2431
}
2519
2524
 */
2520
2525
void
2521
2526
_gabble_connection_acknowledge_set_iq (GabbleConnection *conn,
2522
 
                                       LmMessage *iq)
2523
 
{
2524
 
  LmMessage *result;
2525
 
 
2526
 
  g_assert (LM_MESSAGE_TYPE_IQ == lm_message_get_type (iq));
2527
 
  g_assert (LM_MESSAGE_SUB_TYPE_SET == lm_message_get_sub_type (iq));
2528
 
 
2529
 
  result = lm_iq_message_make_result (iq);
2530
 
 
2531
 
  if (NULL != result)
2532
 
    {
2533
 
      _gabble_connection_send (conn, result, NULL);
2534
 
      lm_message_unref (result);
2535
 
    }
2536
 
}
2537
 
 
2538
 
/**
2539
 
 * _gabble_connection_send_iq_error
2540
 
 *
2541
 
 * Function used to acknowledge an IQ stanza with an error.
2542
 
 */
2543
 
void
2544
 
_gabble_connection_send_iq_error (GabbleConnection *conn,
2545
 
                                  LmMessage *message,
2546
 
                                  GabbleXmppError error,
2547
 
                                  const gchar *errmsg)
2548
 
{
2549
 
  const gchar *to, *id;
2550
 
  LmMessage *msg;
2551
 
  LmMessageNode *iq_node;
2552
 
 
2553
 
  iq_node = lm_message_get_node (message);
2554
 
  to = lm_message_node_get_attribute (iq_node, "from");
2555
 
  id = lm_message_node_get_attribute (iq_node, "id");
2556
 
 
2557
 
  if (id == NULL)
2558
 
    {
2559
 
      NODE_DEBUG (iq_node, "can't acknowledge IQ with no id");
2560
 
      return;
2561
 
    }
2562
 
 
2563
 
  msg = lm_message_new_with_sub_type (to, LM_MESSAGE_TYPE_IQ,
2564
 
                                      LM_MESSAGE_SUB_TYPE_ERROR);
2565
 
 
2566
 
  lm_message_node_set_attribute (wocky_stanza_get_top_node (msg), "id", id);
2567
 
 
2568
 
  lm_message_node_steal_children (
2569
 
      wocky_stanza_get_top_node (msg), iq_node);
2570
 
 
2571
 
  gabble_xmpp_error_to_node (error, wocky_stanza_get_top_node (msg), errmsg);
2572
 
 
2573
 
  _gabble_connection_send (conn, msg, NULL);
2574
 
 
2575
 
  lm_message_unref (msg);
 
2527
                                       WockyStanza *iq)
 
2528
{
 
2529
  wocky_porter_acknowledge_iq (wocky_session_get_porter (conn->session),
 
2530
      iq, NULL);
2576
2531
}
2577
2532
 
2578
2533
static void
2579
2534
add_feature_node (gpointer namespace,
2580
2535
    gpointer result_query)
2581
2536
{
2582
 
  LmMessageNode *feature_node;
 
2537
  WockyNode *feature_node;
2583
2538
 
2584
 
  feature_node = lm_message_node_add_child (result_query, "feature",
 
2539
  feature_node = wocky_node_add_child_with_content (result_query, "feature",
2585
2540
      NULL);
2586
 
  lm_message_node_set_attribute (feature_node, "var", namespace);
 
2541
  wocky_node_set_attribute (feature_node, "var", namespace);
2587
2542
}
2588
2543
 
2589
2544
static void
2590
2545
add_identity_node (const GabbleDiscoIdentity *identity,
2591
2546
    gpointer result_query)
2592
2547
{
2593
 
  LmMessageNode *identity_node;
 
2548
  WockyNode *identity_node;
2594
2549
 
2595
 
  identity_node = lm_message_node_add_child
 
2550
  identity_node = wocky_node_add_child_with_content
2596
2551
      (result_query, "identity", NULL);
2597
 
  lm_message_node_set_attribute (identity_node, "category", identity->category);
2598
 
  lm_message_node_set_attribute (identity_node, "type", identity->type);
 
2552
  wocky_node_set_attribute (identity_node, "category", identity->category);
 
2553
  wocky_node_set_attribute (identity_node, "type", identity->type);
2599
2554
  if (identity->lang)
2600
 
    lm_message_node_set_attribute (identity_node, "lang", identity->lang);
 
2555
    wocky_node_set_attribute (identity_node, "lang", identity->lang);
2601
2556
  if (identity->name)
2602
 
    lm_message_node_set_attribute (identity_node, "name", identity->name);
 
2557
    wocky_node_set_attribute (identity_node, "name", identity->name);
2603
2558
}
2604
2559
 
2605
2560
/**
2721
2676
 
2722
2677
  if (features == NULL && tp_strdiff (suffix, BUNDLE_PMUC_V1))
2723
2678
    {
2724
 
      _gabble_connection_send_iq_error (self, stanza,
2725
 
          XMPP_ERROR_ITEM_NOT_FOUND, NULL);
 
2679
      wocky_porter_send_iq_error (porter, stanza,
 
2680
          WOCKY_XMPP_ERROR_ITEM_NOT_FOUND, NULL);
2726
2681
    }
2727
2682
  else
2728
2683
    {
2763
2718
}
2764
2719
 
2765
2720
/**
2766
 
 * iq_unknown_cb
2767
 
 *
2768
 
 * Called by Wocky when we get an incoming <iq>. This handler is
2769
 
 * at a lower priority than the others, and should reply with an error
2770
 
 * about unsupported get/set attempts.
2771
 
 */
2772
 
static gboolean
2773
 
iq_unknown_cb (WockyPorter *porter,
2774
 
    WockyStanza *stanza,
2775
 
    gpointer user_data)
2776
 
{
2777
 
  GabbleConnection *conn = GABBLE_CONNECTION (user_data);
2778
 
  WockyStanzaSubType subtype;
2779
 
 
2780
 
  wocky_stanza_get_type_info (stanza, NULL, &subtype);
2781
 
 
2782
 
  switch (subtype)
2783
 
    {
2784
 
    case WOCKY_STANZA_SUB_TYPE_GET:
2785
 
    case WOCKY_STANZA_SUB_TYPE_SET:
2786
 
      _gabble_connection_send_iq_error (conn, stanza,
2787
 
          XMPP_ERROR_SERVICE_UNAVAILABLE, NULL);
2788
 
      return TRUE;
2789
 
    default:
2790
 
      break;
2791
 
    }
2792
 
 
2793
 
  return FALSE;
2794
 
}
2795
 
 
2796
 
/**
2797
2721
 * set_status_to_connected
2798
2722
 *
2799
2723
 * Stage 4 of connecting, this function is called once all the events we were
2856
2780
                     GabbleDiscoRequest *request,
2857
2781
                     const gchar *jid,
2858
2782
                     const gchar *node,
2859
 
                     LmMessageNode *result,
 
2783
                     WockyNode *result,
2860
2784
                     GError *disco_error,
2861
2785
                     gpointer user_data)
2862
2786
{
2880
2804
    }
2881
2805
  else
2882
2806
    {
2883
 
      NodeIter i;
 
2807
      WockyNodeIter i;
 
2808
      WockyNode *child;
2884
2809
 
2885
2810
      NODE_DEBUG (result, "got");
2886
2811
 
2887
 
      for (i = node_iter (result); i; i = node_iter_next (i))
 
2812
      wocky_node_iter_init (&i, result, NULL, NULL);
 
2813
      while (wocky_node_iter_next (&i, &child))
2888
2814
        {
2889
 
          LmMessageNode *child = node_iter_data (i);
2890
 
 
2891
2815
          if (0 == strcmp (child->name, "identity"))
2892
2816
            {
2893
 
              const gchar *category = lm_message_node_get_attribute (child,
 
2817
              const gchar *category = wocky_node_get_attribute (child,
2894
2818
                  "category");
2895
 
              const gchar *type = lm_message_node_get_attribute (child, "type");
 
2819
              const gchar *type = wocky_node_get_attribute (child, "type");
2896
2820
 
2897
2821
              if (!tp_strdiff (category, "pubsub") &&
2898
2822
                  !tp_strdiff (type, "pep"))
2903
2827
            }
2904
2828
          else if (0 == strcmp (child->name, "feature"))
2905
2829
            {
2906
 
              const gchar *var = lm_message_node_get_attribute (child, "var");
 
2830
              const gchar *var = wocky_node_get_attribute (child, "var");
2907
2831
 
2908
2832
              if (var == NULL)
2909
2833
                continue;
3810
3734
 
3811
3735
gboolean
3812
3736
gabble_connection_send_presence (GabbleConnection *conn,
3813
 
                                 LmMessageSubType sub_type,
 
3737
                                 WockyStanzaSubType sub_type,
3814
3738
                                 const gchar *contact,
3815
3739
                                 const gchar *status,
3816
3740
                                 GError **error)
3817
3741
{
3818
 
  LmMessage *message;
 
3742
  WockyStanza *message;
3819
3743
  gboolean result;
3820
3744
 
3821
 
  message = lm_message_new_with_sub_type (contact,
3822
 
      LM_MESSAGE_TYPE_PRESENCE,
3823
 
      sub_type);
 
3745
  message = wocky_stanza_build (WOCKY_STANZA_TYPE_PRESENCE, sub_type,
 
3746
      NULL, contact,
 
3747
      NULL);
3824
3748
 
3825
 
  if (LM_MESSAGE_SUB_TYPE_SUBSCRIBE == sub_type)
 
3749
  if (WOCKY_STANZA_SUB_TYPE_SUBSCRIBE == sub_type)
3826
3750
    lm_message_node_add_own_nick (
3827
3751
        wocky_stanza_get_top_node (message), conn);
3828
3752
 
3829
3753
  if (!tp_str_empty (status))
3830
 
    lm_message_node_add_child (
 
3754
    wocky_node_add_child_with_content (
3831
3755
        wocky_stanza_get_top_node (message), "status", status);
3832
3756
 
3833
3757
  result = _gabble_connection_send (conn, message, error);
3834
3758
 
3835
 
  lm_message_unref (message);
 
3759
  g_object_unref (message);
3836
3760
 
3837
3761
  return result;
3838
3762
}
3916
3840
 
3917
3841
/* identities is actually a WockyDiscoIdentityArray */
3918
3842
gchar *
3919
 
gabble_connection_add_sidecar_own_caps_full (GabbleConnection *self,
 
3843
gabble_connection_add_sidecar_own_caps_full (GabblePluginConnection *self,
3920
3844
    const GabbleCapabilitySet *cap_set,
3921
3845
    const GPtrArray *identities,
3922
3846
    GPtrArray *data_forms)
3923
3847
{
 
3848
  GabbleConnection *conn = GABBLE_CONNECTION (self);
3924
3849
  GPtrArray *identities_copy = ((identities == NULL) ?
3925
3850
      wocky_disco_identity_array_new () :
3926
3851
      wocky_disco_identity_array_copy (identities));
3934
3859
 
3935
3860
  ver = gabble_caps_hash_compute_full (cap_set, identities_copy, data_forms);
3936
3861
 
3937
 
  gabble_presence_cache_add_own_caps (self->presence_cache, ver,
 
3862
  gabble_presence_cache_add_own_caps (conn->presence_cache, ver,
3938
3863
      cap_set, identities_copy, data_forms);
3939
3864
 
3940
3865
  wocky_disco_identity_array_free (identities_copy);
3943
3868
}
3944
3869
 
3945
3870
gchar *
3946
 
gabble_connection_add_sidecar_own_caps (GabbleConnection *self,
 
3871
gabble_connection_add_sidecar_own_caps (GabblePluginConnection *self,
3947
3872
    const GabbleCapabilitySet *cap_set,
3948
3873
    const GPtrArray *identities)
3949
3874
{
3952
3877
}
3953
3878
 
3954
3879
const gchar *
3955
 
gabble_connection_get_jid_for_caps (GabbleConnection *conn,
 
3880
gabble_connection_get_jid_for_caps (GabblePluginConnection *plugin_conn,
3956
3881
    WockyXep0115Capabilities *caps)
3957
3882
{
3958
3883
  TpHandle handle;
3959
3884
  TpBaseConnection *base;
3960
3885
  TpHandleRepoIface *contact_handles;
 
3886
  GabbleConnection *conn = GABBLE_CONNECTION (plugin_conn);
3961
3887
 
3962
3888
  g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL);
3963
3889
  g_return_val_if_fail (GABBLE_IS_PRESENCE (caps), NULL);
3981
3907
}
3982
3908
 
3983
3909
const gchar *
3984
 
gabble_connection_pick_best_resource_for_caps (GabbleConnection *connection,
 
3910
gabble_connection_pick_best_resource_for_caps (
 
3911
    GabblePluginConnection *plugin_connection,
3985
3912
    const gchar *jid,
3986
3913
    GabbleCapabilitySetPredicate predicate,
3987
3914
    gconstpointer user_data)
3989
3916
  TpBaseConnection *base;
3990
3917
  TpHandleRepoIface *contact_handles;
3991
3918
  TpHandle handle;
 
3919
  GabbleConnection *connection = GABBLE_CONNECTION (plugin_connection);
3992
3920
  GabblePresence *presence;
3993
3921
 
3994
3922
  g_return_val_if_fail (GABBLE_IS_CONNECTION (connection), NULL);
4022
3950
  return (TpBaseContactList *) connection->roster;
4023
3951
}
4024
3952
 
 
3953
static TpBaseContactList *
 
3954
_gabble_plugin_connection_get_contact_list (
 
3955
    GabblePluginConnection *plugin_connection)
 
3956
{
 
3957
  GabbleConnection *connection = GABBLE_CONNECTION (plugin_connection);
 
3958
  return gabble_connection_get_contact_list (connection);
 
3959
}
 
3960
 
4025
3961
WockyXep0115Capabilities *
4026
 
gabble_connection_get_caps (GabbleConnection *connection,
 
3962
gabble_connection_get_caps (GabblePluginConnection *plugin_connection,
4027
3963
    TpHandle handle)
4028
3964
{
4029
3965
  GabblePresence *presence;
 
3966
  GabbleConnection *connection = GABBLE_CONNECTION (plugin_connection);
4030
3967
 
4031
3968
  g_return_val_if_fail (GABBLE_IS_CONNECTION (connection), NULL);
4032
3969
  g_return_val_if_fail (handle > 0, NULL);