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

« back to all changes in this revision

Viewing changes to src/conn-presence.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:
30
30
#include <telepathy-glib/util.h>
31
31
#include <telepathy-glib/interfaces.h>
32
32
 
33
 
#include <wocky/wocky-c2s-porter.h>
34
 
#include <wocky/wocky-utils.h>
 
33
#include <wocky/wocky.h>
35
34
 
36
35
#define DEBUG_FLAG GABBLE_DEBUG_CONNECTION
37
36
 
58
57
 
59
58
struct _GabbleConnectionPresencePrivate {
60
59
    InvisibilityMethod invisibility_method;
61
 
    LmMessageHandler *iq_list_push_cb;
 
60
    guint iq_list_push_id;
62
61
    gchar *invisible_list_name;
63
62
 
64
63
    /* Mapping between status "show" strings, and shared statuses */
123
122
 
124
123
/* prototypes */
125
124
 
126
 
static LmHandlerResult set_xep0186_invisible_cb (GabbleConnection *conn,
127
 
    LmMessage *sent_msg, LmMessage *reply_msg, GObject *obj,
 
125
static void set_xep0186_invisible_cb (GabbleConnection *conn,
 
126
    WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *obj,
128
127
    gpointer user_data);
129
128
 
130
 
static LmHandlerResult activate_current_privacy_list_cb (
131
 
    GabbleConnection *conn, LmMessage *sent_msg, LmMessage *reply_msg,
 
129
static void activate_current_privacy_list_cb (
 
130
    GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg,
132
131
    GObject *obj, gpointer user_data);
133
132
 
134
133
static void setup_invisible_privacy_list_async (GabbleConnection *self,
135
134
    GAsyncReadyCallback callback, gpointer user_data);
136
135
 
137
 
static LmHandlerResult iq_privacy_list_push_cb (LmMessageHandler *handler,
138
 
    LmConnection *connection, LmMessage *message, gpointer user_data);
 
136
static gboolean iq_privacy_list_push_cb (
 
137
    WockyPorter *porter,
 
138
    WockyStanza *message,
 
139
    gpointer user_data);
139
140
 
140
 
static LmHandlerResult verify_invisible_privacy_list_cb (
141
 
    GabbleConnection *conn, LmMessage *sent_msg, LmMessage *reply_msg,
 
141
static void verify_invisible_privacy_list_cb (
 
142
    GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg,
142
143
    GObject *obj, gpointer user_data);
143
144
 
144
145
static void toggle_presence_visibility_async (GabbleConnection *self,
512
513
          g_object_unref (result);
513
514
        }
514
515
    }
515
 
  else if (!_gabble_connection_send_with_reply (self, (LmMessage *) iq,
 
516
  else if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
516
517
          set_xep0186_invisible_cb, NULL, result, &error))
517
518
    {
518
519
      g_simple_async_result_set_from_error (result, error);
525
526
  g_object_unref (iq);
526
527
}
527
528
 
528
 
static LmHandlerResult
 
529
static void
529
530
set_xep0186_invisible_cb (GabbleConnection *conn,
530
 
    LmMessage *sent_msg,
531
 
    LmMessage *reply_msg,
 
531
    WockyStanza *sent_msg,
 
532
    WockyStanza *reply_msg,
532
533
    GObject *obj,
533
534
    gpointer user_data)
534
535
{
535
536
  GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
536
537
  GError *error = NULL;
537
538
 
538
 
  if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR)
 
539
  if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
539
540
    {
540
541
      g_simple_async_result_set_error (result,
541
542
          CONN_PRESENCE_ERROR, CONN_PRESENCE_ERROR_SET_INVISIBLE,
542
 
          "error setting XEP-0186 (in)visiblity");
 
543
          "error setting XEP-0186 (in)visiblity: %s", error->message);
 
544
      g_clear_error (&error);
543
545
    }
544
546
  else
545
547
    {
561
563
 
562
564
  g_simple_async_result_complete (result);
563
565
  g_object_unref (result);
564
 
 
565
 
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
566
566
}
567
567
 
568
568
 
577
577
  gboolean invisible;
578
578
  GabblePresence *presence = self->self_presence;
579
579
  GError *error = NULL;
580
 
  LmMessageNode *active_node;
 
580
  WockyNode *active_node;
581
581
 
582
582
  g_assert (priv->privacy_statuses != NULL);
583
583
 
607
607
  if (base->status == TP_CONNECTION_STATUS_CONNECTED && invisible)
608
608
    {
609
609
      if (!gabble_connection_send_presence (self,
610
 
              LM_MESSAGE_SUB_TYPE_UNAVAILABLE, NULL, NULL, &error))
 
610
              WOCKY_STANZA_SUB_TYPE_UNAVAILABLE, NULL, NULL, &error))
611
611
        goto ERROR;
612
612
    }
613
613
  /* If we're still connecting and there's no list to be set, we don't
625
625
      goto OUT;
626
626
    }
627
627
 
628
 
  _gabble_connection_send_with_reply (self, (LmMessage *) iq,
 
628
  _gabble_connection_send_with_reply (self, (WockyStanza *) iq,
629
629
      activate_current_privacy_list_cb, NULL, result, &error);
630
630
 
631
631
 ERROR:
641
641
  g_object_unref (iq);
642
642
}
643
643
 
644
 
static LmHandlerResult
 
644
static void
645
645
activate_current_privacy_list_cb (GabbleConnection *conn,
646
 
    LmMessage *sent_msg,
647
 
    LmMessage *reply_msg,
 
646
    WockyStanza *sent_msg,
 
647
    WockyStanza *reply_msg,
648
648
    GObject *obj,
649
649
    gpointer user_data)
650
650
{
651
651
  GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
652
652
  GError *error = NULL;
653
653
 
654
 
  if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR)
 
654
  if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
655
655
    {
656
656
      g_simple_async_result_set_error (result,
657
657
          CONN_PRESENCE_ERROR, CONN_PRESENCE_ERROR_SET_PRIVACY_LIST,
658
 
          "error setting requested privacy list");
 
658
          "error setting requested privacy list: %s", error->message);
 
659
      g_clear_error (&error);
659
660
    }
660
661
  else
661
662
    {
674
675
 
675
676
  g_simple_async_result_complete (result);
676
677
  g_object_unref (result);
677
 
 
678
 
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
679
678
}
680
679
 
681
680
static void
696
695
    }
697
696
}
698
697
 
699
 
static LmHandlerResult
 
698
static void
700
699
create_invisible_privacy_list_reply_cb (GabbleConnection *conn,
701
 
    LmMessage *sent_msg,
702
 
    LmMessage *reply_msg,
 
700
    WockyStanza *sent_msg,
 
701
    WockyStanza *reply_msg,
703
702
    GObject *obj,
704
703
    gpointer user_data)
705
704
{
706
705
  GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
 
706
  GError *error = NULL;
707
707
 
708
 
  if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR)
 
708
  if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
709
709
    {
710
 
      GError *error = gabble_message_get_xmpp_error (reply_msg);
711
 
 
712
710
      g_simple_async_result_set_from_error (result, error);
713
 
 
714
711
      g_free (error);
715
712
    }
716
713
 
717
714
  g_simple_async_result_complete_in_idle (result);
718
715
 
719
716
  g_object_unref (result);
720
 
 
721
 
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
722
717
}
723
718
 
724
719
static void
746
741
 
747
742
  DEBUG ("Creating '%s'", self->presence_priv->invisible_list_name);
748
743
 
749
 
  if (!_gabble_connection_send_with_reply (self, (LmMessage *) iq,
 
744
  if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
750
745
          create_invisible_privacy_list_reply_cb, NULL, result, &error))
751
746
    {
752
747
      g_simple_async_result_set_from_error (result, error);
925
920
  WockyNode *query_node = wocky_node_get_child_ns (
926
921
      wocky_stanza_get_top_node (stanza), "query",
927
922
      NS_GOOGLE_SHARED_STATUS);
928
 
  WockyStanza *result;
929
923
 
930
924
  if (store_shared_statuses (self, query_node))
931
925
    emit_presences_changed_for_self (self);
932
926
 
933
 
  result = wocky_stanza_build_iq_result (stanza, NULL);
934
 
 
935
 
  wocky_porter_send (porter, result);
936
 
 
937
 
  g_object_unref (result);
 
927
  wocky_porter_acknowledge_iq (porter, stanza, NULL);
938
928
 
939
929
  return TRUE;
940
930
}
941
931
 
942
 
static LmHandlerResult
943
 
iq_privacy_list_push_cb (LmMessageHandler *handler,
944
 
    LmConnection *connection,
945
 
    LmMessage *message,
 
932
static gboolean
 
933
iq_privacy_list_push_cb (
 
934
    WockyPorter *porter,
 
935
    WockyStanza *message,
946
936
    gpointer user_data)
947
937
{
948
938
  GabbleConnection *conn = GABBLE_CONNECTION (user_data);
949
 
  LmMessage *result;
950
 
  LmMessageNode *list_node, *iq;
 
939
  WockyNode *list_node, *query_node, *iq;
951
940
  const gchar *list_name;
952
941
 
953
 
  if (lm_message_get_sub_type (message) != LM_MESSAGE_SUB_TYPE_SET)
954
 
    return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
955
 
 
956
 
  iq = lm_message_get_node (message);
957
 
  list_node = lm_message_node_find_child (iq, "list");
958
 
 
959
 
  if (!lm_message_node_get_child_with_namespace (iq, "query", NS_PRIVACY) ||
960
 
      !list_node)
961
 
    return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
962
 
 
963
 
  result = lm_iq_message_make_result (message);
964
 
 
965
 
  wocky_porter_send (wocky_session_get_porter (conn->session), result);
966
 
 
967
 
  list_name = lm_message_node_get_attribute (list_node, "name");
 
942
  wocky_porter_acknowledge_iq (wocky_session_get_porter (conn->session),
 
943
      message, NULL);
 
944
 
 
945
  iq = wocky_stanza_get_top_node (message);
 
946
  query_node = wocky_node_get_first_child (iq);
 
947
  list_node = wocky_node_get_child (query_node, "list");
 
948
  list_name = wocky_node_get_attribute (list_node, "name");
968
949
 
969
950
  if (g_strcmp0 (list_name, conn->presence_priv->invisible_list_name) == 0)
970
951
    setup_invisible_privacy_list_async (conn, NULL, NULL);
971
952
 
972
 
  lm_message_unref (result);
973
 
 
974
 
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
 
953
  return TRUE;
975
954
}
976
955
 
977
956
/**********************************************************************
1099
1078
  wocky_implement_finish_void (self, get_shared_status_async);
1100
1079
}
1101
1080
 
1102
 
static LmHandlerResult
 
1081
static void
1103
1082
get_existing_privacy_lists_cb (GabbleConnection *conn,
1104
 
    LmMessage *sent_msg,
1105
 
    LmMessage *reply_msg,
 
1083
    WockyStanza *sent_msg,
 
1084
    WockyStanza *reply_msg,
1106
1085
    GObject *obj,
1107
1086
    gpointer user_data)
1108
1087
{
1109
1088
  GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
1110
1089
  WockyNode *query_node = wocky_node_get_child_ns (
1111
1090
      wocky_stanza_get_top_node (reply_msg), "query", NS_PRIVACY);
1112
 
  GError *error = gabble_message_get_xmpp_error (reply_msg);
 
1091
  GError *error = NULL;
1113
1092
 
1114
 
  if (error != NULL)
 
1093
  if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
1115
1094
    {
1116
1095
      DEBUG ("Error getting privacy lists: %s", error->message);
1117
1096
 
1127
1106
  else
1128
1107
    {
1129
1108
      GabbleConnectionPresencePrivate *priv = conn->presence_priv;
1130
 
      LmMessageNode *list_node;
 
1109
      WockyNode *list_node;
1131
1110
      WockyNodeIter iter;
1132
1111
      GabblePluginLoader *loader = gabble_plugin_loader_dup ();
1133
1112
 
1141
1120
      wocky_node_iter_init (&iter, query_node, "list", NULL);
1142
1121
      while (wocky_node_iter_next (&iter, &list_node))
1143
1122
        {
1144
 
          const gchar *list_name = lm_message_node_get_attribute (list_node,
 
1123
          const gchar *list_name = wocky_node_get_attribute (list_node,
1145
1124
              "name");
1146
1125
          const gchar *status_name;
1147
1126
 
1162
1141
 
1163
1142
  g_simple_async_result_complete_in_idle (result);
1164
1143
  g_object_unref (result);
1165
 
 
1166
 
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
1167
1144
}
1168
1145
 
1169
1146
static void
1183
1160
        ')',
1184
1161
      NULL);
1185
1162
 
1186
 
  if (!_gabble_connection_send_with_reply (self, (LmMessage *) iq,
 
1163
  if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
1187
1164
          get_existing_privacy_lists_cb, NULL, result, &error))
1188
1165
    {
1189
1166
      g_simple_async_result_set_from_error (result, error);
1229
1206
        ')',
1230
1207
      NULL);
1231
1208
 
1232
 
  if (!_gabble_connection_send_with_reply (self, (LmMessage *) iq,
 
1209
  if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
1233
1210
          verify_invisible_privacy_list_cb, NULL, result, &error))
1234
1211
    {
1235
1212
      g_simple_async_result_set_from_error (result, error);
1251
1228
}
1252
1229
 
1253
1230
static gboolean
1254
 
is_valid_invisible_list (LmMessageNode *list_node)
 
1231
is_valid_invisible_list (WockyNode *list_node)
1255
1232
{
1256
 
  LmMessageNode *top_node = NULL;
1257
 
  NodeIter i;
 
1233
  WockyNode *top_node = NULL;
 
1234
  WockyNode *child;
 
1235
  WockyNodeIter i;
1258
1236
  guint top_order = G_MAXUINT;
1259
1237
 
1260
 
  for (i = node_iter (list_node); i; i = node_iter_next (i))
 
1238
  wocky_node_iter_init (&i, list_node, "item", NULL);
 
1239
  while (wocky_node_iter_next (&i, &child))
1261
1240
    {
1262
 
      LmMessageNode *child = node_iter_data (i);
1263
1241
      const gchar *order_str;
1264
1242
      guint order;
1265
1243
      gchar *end;
1266
1244
 
1267
 
      if (g_strcmp0 (lm_message_node_get_name (child), "item") != 0)
1268
 
        continue;
1269
 
 
1270
 
      order_str = lm_message_node_get_attribute (child, "order");
 
1245
      order_str = wocky_node_get_attribute (child, "order");
1271
1246
 
1272
1247
      if (order_str == NULL)
1273
1248
        continue;
1286
1261
 
1287
1262
  if (top_node != NULL)
1288
1263
    {
1289
 
      const gchar *value = lm_message_node_get_attribute (top_node, "value");
1290
 
      const gchar *action = lm_message_node_get_attribute (top_node, "action");
1291
 
      LmMessageNode *presence_out = lm_message_node_get_child (top_node,
 
1264
      const gchar *value = wocky_node_get_attribute (top_node, "value");
 
1265
      const gchar *action = wocky_node_get_attribute (top_node, "action");
 
1266
      WockyNode *presence_out = wocky_node_get_child (top_node,
1292
1267
          "presence-out");
1293
1268
 
1294
1269
      return (value == NULL && g_strcmp0 (action, "deny") == 0 &&
1298
1273
  return FALSE;
1299
1274
}
1300
1275
 
1301
 
static LmHandlerResult
 
1276
static void
1302
1277
verify_invisible_privacy_list_cb (GabbleConnection *conn,
1303
 
    LmMessage *sent_msg,
1304
 
    LmMessage *reply_msg,
 
1278
    WockyStanza *sent_msg,
 
1279
    WockyStanza *reply_msg,
1305
1280
    GObject *obj,
1306
1281
    gpointer user_data)
1307
1282
{
1308
1283
  GabbleConnectionPresencePrivate *priv = conn->presence_priv;
1309
 
  LmMessageNode *node = lm_message_node_find_child
1310
 
    (wocky_stanza_get_top_node (reply_msg), "list");
1311
 
  GError *error = gabble_message_get_xmpp_error (reply_msg);
1312
 
 
1313
 
  if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_RESULT &&
1314
 
      node != NULL)
 
1284
  WockyNode *query_node, *list_node = NULL;
 
1285
  GError *error = NULL;
 
1286
 
 
1287
  query_node = wocky_node_get_child_ns (wocky_stanza_get_top_node (reply_msg),
 
1288
      "query", NS_PRIVACY);
 
1289
 
 
1290
  if (query_node != NULL)
 
1291
    list_node = wocky_node_get_child (query_node, "list");
 
1292
 
 
1293
  if (!wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL) &&
 
1294
      list_node != NULL)
1315
1295
    {
1316
 
      if (!is_valid_invisible_list (node))
 
1296
      if (!is_valid_invisible_list (list_node))
1317
1297
        {
1318
1298
          g_free (priv->invisible_list_name);
1319
1299
          priv->invisible_list_name = g_strdup ("invisible-gabble");
1331
1311
          toggle_presence_visibility_async (conn,
1332
1312
              toggle_initial_presence_visibility_cb, user_data);
1333
1313
        }
1334
 
 
1335
 
      goto OUT;
1336
 
    }
1337
 
  else if (error != NULL)
1338
 
    {
1339
 
      if (error->code == XMPP_ERROR_ITEM_NOT_FOUND)
1340
 
        {
1341
 
          create_invisible_privacy_list_async (conn,
1342
 
              create_invisible_privacy_list_cb, user_data);
1343
 
          goto OUT;
1344
 
        }
1345
 
    }
1346
 
 
1347
 
  disable_invisible_privacy_list (conn);
1348
 
 
1349
 
  toggle_presence_visibility_async (conn,
1350
 
      toggle_initial_presence_visibility_cb, user_data);
1351
 
 
1352
 
 OUT:
 
1314
    }
 
1315
  else if (error->code == WOCKY_XMPP_ERROR_ITEM_NOT_FOUND)
 
1316
    {
 
1317
      create_invisible_privacy_list_async (conn,
 
1318
          create_invisible_privacy_list_cb, user_data);
 
1319
    }
 
1320
  else
 
1321
    {
 
1322
      disable_invisible_privacy_list (conn);
 
1323
 
 
1324
      toggle_presence_visibility_async (conn,
 
1325
          toggle_initial_presence_visibility_cb, user_data);
 
1326
    }
 
1327
 
1353
1328
  if (error != NULL)
1354
1329
    g_error_free (error);
1355
 
 
1356
 
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
1357
1330
}
1358
1331
 
1359
1332
static void
1373
1346
      g_error_free (error);
1374
1347
    }
1375
1348
 
1376
 
  if (priv->invisibility_method == INVISIBILITY_METHOD_PRIVACY)
 
1349
  if (priv->invisibility_method == INVISIBILITY_METHOD_PRIVACY &&
 
1350
      self->session != NULL)
1377
1351
    {
1378
 
      priv->iq_list_push_cb = lm_message_handler_new (iq_privacy_list_push_cb,
1379
 
          self, NULL);
1380
 
 
1381
 
      lm_connection_register_message_handler (self->lmconn,
1382
 
          priv->iq_list_push_cb, LM_MESSAGE_TYPE_IQ,
1383
 
          LM_HANDLER_PRIORITY_NORMAL);
 
1352
      priv->iq_list_push_id = wocky_c2s_porter_register_handler_from_server (
 
1353
          WOCKY_C2S_PORTER (wocky_session_get_porter (self->session)),
 
1354
          WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET,
 
1355
          WOCKY_PORTER_HANDLER_PRIORITY_NORMAL,
 
1356
          iq_privacy_list_push_cb, self,
 
1357
          '(', "query", ':', NS_PRIVACY,
 
1358
            '(', "list", ')',
 
1359
          ')', NULL);
1384
1360
    }
1385
1361
 
1386
1362
  g_simple_async_result_complete_in_idle (external_result);
1593
1569
  GabbleConnectionPresencePrivate *priv = self->presence_priv;
1594
1570
  GabblePresence *presence = self->self_presence;
1595
1571
  TpBaseConnection *base = (TpBaseConnection *) self;
1596
 
  LmMessage *message = gabble_presence_as_message (presence, to);
 
1572
  WockyStanza *message = gabble_presence_as_message (presence, to);
1597
1573
  gboolean ret;
1598
1574
 
1599
1575
  if (presence->status == GABBLE_PRESENCE_HIDDEN && to == NULL)
1600
1576
    {
1601
1577
      if (priv->invisibility_method == INVISIBILITY_METHOD_PRESENCE_INVISIBLE)
1602
 
        lm_message_node_set_attribute (lm_message_get_node (message),
 
1578
        wocky_node_set_attribute (wocky_stanza_get_top_node (message),
1603
1579
            "type", "invisible");
1604
1580
      /* FIXME: or if sending directed presence, should we add
1605
1581
       * <show>away</show>? */
1609
1585
 
1610
1586
  ret = _gabble_connection_send (self, message, error);
1611
1587
 
1612
 
  lm_message_unref (message);
 
1588
  g_object_unref (message);
1613
1589
 
1614
1590
  /* FIXME: if sending broadcast presence, should we echo it to everyone we
1615
1591
   * previously sent directed presence to? (Perhaps also GC them after a
2021
1997
      wocky_porter_unregister_handler (porter, priv->iq_shared_status_cb);
2022
1998
      priv->iq_shared_status_cb = 0;
2023
1999
    }
 
2000
 
 
2001
  if (priv->iq_list_push_id != 0)
 
2002
    {
 
2003
      wocky_porter_unregister_handler (porter, priv->iq_list_push_id);
 
2004
      priv->iq_list_push_id = 0;
 
2005
    }
2024
2006
}
2025
2007
 
2026
2008
void
2036
2018
  if (priv->shared_statuses != NULL)
2037
2019
      g_hash_table_unref (priv->shared_statuses);
2038
2020
 
2039
 
  if (priv->iq_list_push_cb != NULL)
2040
 
    lm_message_handler_unref (priv->iq_list_push_cb);
2041
 
 
2042
2021
  g_slice_free (GabbleConnectionPresencePrivate, priv);
2043
2022
 
2044
2023
  tp_presence_mixin_finalize ((GObject *) conn);