telepathygabble/src/jingle-info.c
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:10:06 +0200
changeset 0 d0f3a028347a
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
 * jingle-info.c - Source for Jingle info discovery
 * Copyright (C) 2006 Collabora Ltd.
 * Portions  and/or its subsidiary/subsidiaries.All rights reserved.
 *   @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <string.h>
#include <stdlib.h>

#define DEBUG_FLAG GABBLE_DEBUG_MEDIA

#include "debug.h"
#include "jingle-info.h"
#include "gabble-error.h"
#include "namespaces.h"
#include "util.h"

#ifdef DEBUG_FLAG
//#define DEBUG(format, ...)
#define DEBUGGING 0
#define NODE_DEBUG(n, s)
#endif /* DEBUG_FLAG */

/**
 * jingle_info_discover_servers:
 *
 * Discover available Jingle servers.
 *
 * @conn: The GabbleConnection# object initiating the discovery.
 */
void
jingle_info_discover_servers (GabbleConnection *conn)
{
  LmMessage *msg = NULL;
  LmMessageNode *node;
  GError *error = NULL;
  GabbleHandle handle = conn->self_handle;
  const gchar *jid = gabble_handle_inspect (conn->handles, TP_HANDLE_TYPE_CONTACT, handle);

  msg = lm_message_new_with_sub_type (jid, LM_MESSAGE_TYPE_IQ,
                                      LM_MESSAGE_SUB_TYPE_GET);

  node = lm_message_node_add_child (msg->node, "query", NULL);
  lm_message_node_set_attribute (node, "xmlns", NS_GOOGLE_JINGLE_INFO);

  if (!_gabble_connection_send (conn, msg, &error))
    {
      g_warning ("%s: send failed: %s\n", G_STRFUNC, error->message);
      goto OUT;
    }

OUT:
  if (msg)
    lm_message_unref (msg);

  if (error)
    g_error_free (error);
}


/**
 * jingle_info_iq_callback
 *
 * Called by loudmouth when we get an incoming <iq>. This handler
 * is concerned only with Jingle info queries.
 */
LmHandlerResult
jingle_info_iq_callback (LmMessageHandler *handler,
                         LmConnection *lmconn,
                         LmMessage *message,
                         gpointer user_data)
{
  GabbleConnection *conn = GABBLE_CONNECTION (user_data);
  LmMessageSubType sub_type;
  LmMessageNode *query_node, *parent_node, *node;
  const gchar *str;
  guint port;

  if ( NULL == conn )
        {
        g_debug ("%s: accesing after dereferenced connection", G_STRFUNC);
        return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
        }
  
  query_node = lm_message_node_get_child_with_namespace (message->node,
      "query", NS_GOOGLE_JINGLE_INFO);

  if (query_node == NULL)
    return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;

  NODE_DEBUG (message->node, "got");

  sub_type = lm_message_get_sub_type (message);

  if (sub_type == LM_MESSAGE_SUB_TYPE_RESULT ||
      sub_type == LM_MESSAGE_SUB_TYPE_SET)
    {
      parent_node = lm_message_node_get_child (query_node, "stun");
      if (parent_node)
        {
          for (node = parent_node->children; node; node = node->next)
            {
              if (strcmp (node->name, "server") == 0)
                {
                  str = lm_message_node_get_attribute (node, "host");
                  if (str)
                    {
                      gabble_debug (DEBUG_FLAG, "setting 'stun-server' to '%s'", str);

                      g_object_set (conn, "stun-server", str, NULL);
                    }

                  str = lm_message_node_get_attribute (node, "udp");
                  if (str)
                    {
                      port = atoi (str);

                      gabble_debug (DEBUG_FLAG, "setting 'stun-port' to %d", port);

                      g_object_set (conn, "stun-port", port, NULL);
                    }

                  /* only grab the first one for now */
                  break;
                }
            }
        }

      parent_node = lm_message_node_get_child (query_node, "relay");
      if (parent_node)
        {
          gboolean found_server = FALSE;

          for (node = parent_node->children; node; node = node->next)
            {
              if (!found_server && strcmp (node->name, "server") == 0)
                {
                  str = lm_message_node_get_attribute (node, "host");
                  if (str)
                    {
                      gabble_debug (DEBUG_FLAG, "setting 'stun-relay-server' to '%s'",
                               str);

                      g_object_set (conn, "stun-relay-server", str, NULL);
                    }

                  str = lm_message_node_get_attribute (node, "udp");
                  if (str)
                    {
                      port = atoi (str);

                      gabble_debug (DEBUG_FLAG, "setting 'stun-relay-udp-port' to %d",
                               port);

                      g_object_set (conn, "stun-relay-udp-port", port, NULL);
                    }

                  str = lm_message_node_get_attribute (node, "tcp");
                  if (str)
                    {
                      port = atoi (str);

                      gabble_debug (DEBUG_FLAG, "setting 'stun-relay-tcp-port' to %d",
                               port);

                      g_object_set (conn, "stun-relay-tcp-port", port, NULL);
                    }

                  str = lm_message_node_get_attribute (node, "tcpssl");
                  if (str)
                    {
                      port = atoi (str);

                      gabble_debug (DEBUG_FLAG, "setting 'stun-relay-ssltcp-port' to %d",
                               port);

                      g_object_set (conn, "stun-relay-ssltcp-port", port, NULL);
                    }

                  found_server = TRUE;
                }
              else if (strcmp (node->name, "token") == 0)
                {
                  str = lm_message_node_get_value (node);
                  if (str)
                    {
                      gabble_debug (DEBUG_FLAG, "setting 'stun-relay-magic-cookie' to '%s'",
                               str);

                      g_object_set (conn, "stun-relay-magic-cookie", str, NULL);
                    }
                }
            }
        }

      if (sub_type == LM_MESSAGE_SUB_TYPE_SET)
        {
          _gabble_connection_acknowledge_set_iq (conn, message);
        }
    }
  else if (sub_type == LM_MESSAGE_SUB_TYPE_ERROR)
    {
      GabbleXmppError xmpp_error = INVALID_XMPP_ERROR;

      node = lm_message_node_get_child (message->node, "error");
      if (node)
        {
          xmpp_error = gabble_xmpp_error_from_node (node);
        }

      str = gabble_xmpp_error_string (xmpp_error);

      g_warning ("%s: jingle info error: %s", G_STRFUNC,
          (str) ? str : "unknown error");
    }
  else
    {
      NODE_DEBUG (message->node, "unknown message sub type");
    }

  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}