示例#1
0
/* Signals incoming delivery receipts. http://xmpp.org/extensions/xep-0184.html
 */
static gboolean
im_factory_receipt_cb (
    WockyPorter *porter,
    WockyStanza *message,
    gpointer user_data)
{
  GabbleImFactory *self = GABBLE_IM_FACTORY (user_data);
  WockyNode *received;
  const gchar *from, *received_id;
  GabbleIMChannel *channel;

  received = wocky_node_get_child_ns (wocky_stanza_get_top_node (message),
      "received", NS_RECEIPTS);
  g_return_val_if_fail (received != NULL, FALSE);

  received_id = wocky_node_get_attribute (received, "id");
  if (received_id == NULL)
    {
      STANZA_DEBUG (message, "but *what* did you receive?!");
      return TRUE;
    }

  from = wocky_stanza_get_from (message);
  channel = get_channel_for_incoming_message (self, from, FALSE);
  if (channel == NULL)
    {
      DEBUG ("no existing channel with '%s'; ignoring receipt", from);
      return TRUE;
    }

  gabble_im_channel_receive_receipt (channel, received_id);
  return TRUE;
}
/*
 * gabble_bytestream_multiple_accept
 *
 * Implements gabble_bytestream_iface_accept on GabbleBytestreamIface
 */
static void
gabble_bytestream_multiple_accept (GabbleBytestreamIface *iface,
                                   GabbleBytestreamAugmentSiAcceptReply func,
                                   gpointer user_data)
{
  GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (iface);
  GabbleBytestreamMultiplePrivate *priv =
      GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self);
  WockyStanza *msg;
  WockyNode *si;
  GList *all_methods;
  gchar *current_method;

  /* We cannot just call the accept method of the active bytestream because
   * the result stanza is different if we are using si-multiple */

  if (priv->state != GABBLE_BYTESTREAM_STATE_LOCAL_PENDING)
    {
      /* The stream was previoulsy or automatically accepted */
      return;
    }

  g_return_if_fail (priv->active_bytestream != NULL);

  all_methods = g_list_copy (priv->fallback_stream_methods);
  g_object_get (priv->active_bytestream, "protocol", &current_method, NULL);
  all_methods = g_list_prepend (all_methods, current_method);

  msg = gabble_bytestream_factory_make_multi_accept_iq (priv->peer_jid,
      priv->stream_init_id, all_methods);

  g_free (current_method);
  g_list_free (all_methods);

  si = wocky_node_get_child_ns (
    wocky_stanza_get_top_node (msg), "si", NS_SI);
  g_assert (si != NULL);

  if (func != NULL)
    {
      /* let the caller add his profile specific data */
      func (si, user_data);
    }

  if (_gabble_connection_send (priv->conn, msg, NULL))
    {
      DEBUG ("stream %s with %s is now accepted", priv->stream_id,
          priv->peer_jid);
      g_object_set (priv->active_bytestream, "state",
          GABBLE_BYTESTREAM_STATE_ACCEPTED, NULL);
    }

  g_object_unref (msg);
}
示例#3
0
static void
got_jingle_info_stanza (
    GabbleJingleInfo *self,
    WockyStanza *stanza)
{
  WockyNode *node, *query_node;

  query_node = wocky_node_get_child_ns (
      wocky_stanza_get_top_node (stanza), "query", NS_GOOGLE_JINGLE_INFO);

  if (query_node == NULL)
    return;

  if (self->priv->get_stun_from_jingle)
    node = wocky_node_get_child (query_node, "stun");
  else
    node = NULL;

  if (node != NULL)
    {
      node = wocky_node_get_child (node, "server");

      if (node != NULL)
        {
          const gchar *server;
          const gchar *port_attr;
          guint port = 0;

          server = wocky_node_get_attribute (node, "host");
          port_attr = wocky_node_get_attribute (node, "udp");

          if (port_attr != NULL)
            port = atoi (port_attr);

          if (server != NULL &&
              port_attr != NULL && port > 0 && port <= G_MAXUINT16)
            {
              DEBUG ("jingle info: got stun server %s, port %u", server,
                  port);
              gabble_jingle_info_take_stun_server (self,
                  g_strdup (server), port, FALSE);
            }
        }
    }

#ifdef ENABLE_GOOGLE_RELAY
  node = wocky_node_get_child (query_node, "relay");

  if (node != NULL)
    {
      WockyNode *subnode = wocky_node_get_child (node, "token");

      if (subnode != NULL)
        {
          const gchar *token = subnode->content;

          if (token != NULL)
            {
              DEBUG ("jingle info: got Google relay token %s", token);
              g_free (self->priv->relay_token);
              self->priv->relay_token = g_strdup (token);
            }
        }

      subnode = wocky_node_get_child (node, "server");

      if (subnode != NULL)
        {
          const gchar *server;
          const gchar *port;

          server = wocky_node_get_attribute (subnode, "host");

          if (server != NULL)
            {
              DEBUG ("jingle info: got relay server %s", server);
              g_free (self->priv->relay_server);
              self->priv->relay_server = g_strdup (server);
            }

          if (test_mode)
            {
              /* this is not part of the real protocol, but we can't listen on
               * port 80 in an unprivileged regression test */
              port = wocky_node_get_attribute (subnode,
                  "gabble-test-http-port");

              if (port != NULL)
                {
                  DEBUG ("jingle info: diverting 'Google' HTTP requests to "
                      "port %s", port);
                  self->priv->relay_http_port = atoi (port);
                }
            }

          /* FIXME: these are not really actually used anywhere at
           * the moment, because we get the same info when creating
           * relay session. */
          port = wocky_node_get_attribute (subnode, "udp");

          if (port != NULL)
            {
              DEBUG ("jingle info: got relay udp port %s", port);
              self->priv->relay_udp = atoi (port);
            }

          port = wocky_node_get_attribute (subnode, "tcp");

          if (port != NULL)
            {
              DEBUG ("jingle info: got relay tcp port %s", port);
              self->priv->relay_tcp = atoi (port);
            }

          port = wocky_node_get_attribute (subnode, "tcpssl");

          if (port != NULL)
            {
              DEBUG ("jingle info: got relay tcpssl port %s", port);
              self->priv->relay_ssltcp = atoi (port);
            }

        }

    }
#endif  /* ENABLE_GOOGLE_RELAY */
}
static void
iq_set_bind_XMPP_BIND (TestConnectorServer *self,
    WockyStanza *xml)
{
  TestConnectorServerPrivate *priv = self->priv;
  WockyXmppConnection *conn = priv->conn;
  WockyStanza *iq = NULL;
  BindProblem problems = priv->problem.connector->bind;
  BindProblem bp = BIND_PROBLEM_NONE;

  DEBUG("");
  if ((bp = problems & BIND_PROBLEM_INVALID)  ||
      (bp = problems & BIND_PROBLEM_DENIED)   ||
      (bp = problems & BIND_PROBLEM_CONFLICT) ||
      (bp = problems & BIND_PROBLEM_REJECTED))
    {
      const gchar *error = NULL;
      const gchar *etype = NULL;
      switch (bp)
        {
        case BIND_PROBLEM_INVALID:
          error = "bad-request";
          etype = "modify";
          break;
        case BIND_PROBLEM_DENIED:
          error = "not-allowed";
          etype = "cancel";
          break;
        case BIND_PROBLEM_CONFLICT:
          error = "conflict";
          etype = "cancel";
          break;
        default:
          error = "badger-badger-badger-mushroom";
          etype = "moomins";
        }
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_ERROR,
          NULL, NULL,
          '(', "bind", ':', WOCKY_XMPP_NS_BIND,
          ')',
          '(', "error", '@', "type", etype,
          '(', error, ':', WOCKY_XMPP_NS_STANZAS,
          ')',
          ')',
          NULL);
    }
  else if (problems & BIND_PROBLEM_FAILED)
    {
      /* deliberately nonsensical response */
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_SET,
          NULL, NULL,
          '(', "bind", ':', WOCKY_XMPP_NS_BIND,
          ')',
          NULL);
    }
  else if (problems & BIND_PROBLEM_NONSENSE)
    {
      /* deliberately nonsensical response */
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE,
          WOCKY_STANZA_SUB_TYPE_NONE,
          NULL, NULL,
          '(', "bind", ':', WOCKY_XMPP_NS_BIND,
          ')',
          NULL);
    }
  else if (problems & BIND_PROBLEM_CLASH)
    {
      iq = error_stanza ("conflict", NULL, FALSE);
    }
  else
    {
      WockyNode *ciq = wocky_stanza_get_top_node (xml);
      WockyNode *bind =
        wocky_node_get_child_ns (ciq, "bind", WOCKY_XMPP_NS_BIND);
      WockyNode *res = wocky_node_get_child (bind, "resource");
      const gchar *uniq = NULL;
      gchar *jid = NULL;

      if (res != NULL)
        uniq = res->content;
      if (uniq == NULL)
        uniq = "a-made-up-resource";

      if (problems & BIND_PROBLEM_NO_JID)
        {
          iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
              WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL,
              '(', "bind", ':', WOCKY_XMPP_NS_BIND,
              ')', NULL);
        }
      else
        {
          jid = g_strdup_printf ("[email protected]/%s", uniq);
          iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
              WOCKY_STANZA_SUB_TYPE_RESULT,
              NULL, NULL,
              '(', "bind", ':', WOCKY_XMPP_NS_BIND,
              '(', "jid", '$', jid, ')',
              ')',
              NULL);
          g_free (jid);
        }
    }

  server_enc_outstanding (self);
  wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancellable,
    iq_sent, self);
  g_object_unref (xml);
  g_object_unref (iq);
}
static void
xmpp_handler (GObject *source,
    GAsyncResult *result,
    gpointer user_data)
{
  TestConnectorServer *self;
  TestConnectorServerPrivate *priv;
  WockyStanza *xml = NULL;
  WockyXmppConnection *conn = NULL;
  const gchar *ns = NULL;
  const gchar *name = NULL;
  gboolean handled = FALSE;
  GError *error = NULL;
  WockyStanzaType type = WOCKY_STANZA_TYPE_NONE;
  WockyStanzaSubType subtype = WOCKY_STANZA_SUB_TYPE_NONE;
  int i;

  DEBUG ("");
  self = TEST_CONNECTOR_SERVER (user_data);
  priv = self->priv;
  conn = priv->conn;
  xml  = wocky_xmpp_connection_recv_stanza_finish (conn, result, &error);

  /* A real XMPP server would need to do some error handling here, but if
   * we got this far, we can just exit: The client (ie the test) will
   * report any error that actually needs reporting - we don't need to */
  if (error != NULL)
    {
      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
        {
          g_error_free (error);
          server_dec_outstanding (self);
          return;
        }
      g_assert_not_reached ();
    }

  if (server_dec_outstanding (self))
    return;

  ns   = wocky_node_get_ns (wocky_stanza_get_top_node (xml));
  name = wocky_stanza_get_top_node (xml)->name;
  wocky_stanza_get_type_info (xml, &type, &subtype);

  /* if we find a handler, the handler is responsible for listening for the
     next stanza and setting up the next callback in the chain: */
  if (type == WOCKY_STANZA_TYPE_IQ)
    for (i = 0; iq_handlers[i].payload != NULL; i++)
      {
        iq_handler *iq = &iq_handlers[i];
        WockyNode *payload =
          wocky_node_get_child_ns (wocky_stanza_get_top_node (xml),
              iq->payload, iq->ns);
        /* namespace, stanza subtype and payload tag name must match: */
        if ((payload == NULL) || (subtype != iq->subtype))
          continue;
        DEBUG ("test_connector_server:invoking iq handler %s", iq->payload);
        (iq->func) (self, xml);
        handled = TRUE;
        break;
      }
  else
    for (i = 0; handlers[i].ns != NULL; i++)
      {
        if (!strcmp (ns, handlers[i].ns) && !strcmp (name, handlers[i].name))
          {
            DEBUG ("test_connector_server:invoking handler %s.%s", ns, name);
            (handlers[i].func) (self, xml);
            handled = TRUE;
            break;
          }
      }

  /* no handler found: just complain and sit waiting for the next stanza */
  if (!handled)
    {
      DEBUG ("<%s xmlns=\"%s\"… not handled", name, ns);
      server_enc_outstanding (self);
      wocky_xmpp_connection_recv_stanza_async (conn, priv->cancellable,
          xmpp_handler, self);
      g_object_unref (xml);
    }
}
示例#6
0
static gboolean
update_location_from_item (
    GabbleConnection *conn,
    TpHandle contact,
    WockyNode *item_node)
{
  WockyNode *node;
  GHashTable *location = g_hash_table_new_full (g_direct_hash, g_direct_equal,
      g_free, (GDestroyNotify) tp_g_value_slice_free);
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
      (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT);
  const gchar *from = tp_handle_inspect (contact_repo, contact);
  WockyNodeIter i;
  WockyNode *subloc_node;
  const gchar *lang;

  if (item_node == NULL)
    return FALSE;

  node = wocky_node_get_child_ns (item_node, "geoloc", NS_GEOLOC);
  if (node == NULL)
    return FALSE;

  DEBUG ("LocationsUpdate for %s:", from);

  lang = wocky_node_get_language (node);
  if (lang != NULL)
    {
      g_hash_table_insert (location, g_strdup ("language"),
          tp_g_value_slice_new_string (lang));
    }

  build_mapping_tables ();

  wocky_node_iter_init (&i, node, NULL, NULL);
  while (wocky_node_iter_next (&i, &subloc_node))
    {
      GValue *value = NULL;
      gchar *xmpp_name;
      const gchar *str;
      LocationMapping *mapping;

      xmpp_name = subloc_node->name;
      str = subloc_node->content;
      if (str == NULL)
        continue;

      mapping = g_hash_table_lookup (xmpp_to_tp, xmpp_name);
      if (mapping == NULL)
        {
          DEBUG ("Unknown location attribute: %s\n", xmpp_name);
          continue;
        }

      if (mapping->type == G_TYPE_DOUBLE)
        {
          gdouble double_value;
          gchar *end;

          double_value = g_ascii_strtod (str, &end);

          if (end == str)
            continue;

          value = tp_g_value_slice_new_double (double_value);
          DEBUG ("\t - %s: %f", xmpp_name, double_value);
        }
      else if (strcmp (xmpp_name, "timestamp") == 0)
        {
          GTimeVal timeval;
          if (g_time_val_from_iso8601 (str, &timeval))
            {
              value = tp_g_value_slice_new_int64 (timeval.tv_sec);
              DEBUG ("\t - %s: %s", xmpp_name, str);
            }
          else
            {
              DEBUG ("\t - %s: %s: unknown date format", xmpp_name, str);
              continue;
            }
        }
      else if (mapping->type == G_TYPE_STRING)
        {
          value = tp_g_value_slice_new_string (str);
          DEBUG ("\t - %s: %s", xmpp_name, str);
        }
      else
        {
          g_assert_not_reached ();
        }

      g_hash_table_insert (location, g_strdup (mapping->tp_name), value);
    }

  tp_svc_connection_interface_location_emit_location_updated (conn,
      contact, location);
  gabble_presence_cache_update_location (conn->presence_cache, contact,
      location);

  return TRUE;
}