Logo Search packages:      
Sourcecode: kadu version File versions

netnames.cpp

/*
 * Copyright (C) 2006  Justin Karneges
 *
 * 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 Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 *
 */

#include "netnames.h"

//#include <idna.h>
#include "irisnetplugin.h"
#include "irisnetglobal_p.h"
#include "addressresolver.h"

namespace XMPP {

//----------------------------------------------------------------------------
// NameRecord
//----------------------------------------------------------------------------
00033 class NameRecord::Private : public QSharedData
{
public:
      QByteArray owner;
      NameRecord::Type type;
      int ttl;

      QHostAddress address;
      QByteArray name;
      int priority, weight, port;
      QList<QByteArray> texts;
      QByteArray cpu, os;
      QByteArray rawData;
};

#define ENSURE_D { if(!d) d = new Private; }

00050 NameRecord::NameRecord()
{
      d = 0;
}

00055 NameRecord::NameRecord(const QByteArray &owner, int ttl)
{
      d = 0;
      setOwner(owner);
      setTtl(ttl);
}

00062 NameRecord::NameRecord(const NameRecord &from)
{
      d = 0;
      *this = from;
}

00068 NameRecord::~NameRecord()
{
}

00072 NameRecord & NameRecord::operator=(const NameRecord &from)
{
      d = from.d;
      return *this;
}

00078 bool NameRecord::isNull() const
{
      return (d ? false : true);
}

00083 QByteArray NameRecord::owner() const
{
      Q_ASSERT(d);
      return d->owner;
}

00089 int NameRecord::ttl() const
{
      Q_ASSERT(d);
      return d->ttl;
}

00095 NameRecord::Type NameRecord::type() const
{
      Q_ASSERT(d);
      return d->type;
}

00101 QHostAddress NameRecord::address() const
{
      Q_ASSERT(d);
      return d->address;
}

00107 QByteArray NameRecord::name() const
{
      Q_ASSERT(d);
      return d->name;
}

00113 int NameRecord::priority() const
{
      Q_ASSERT(d);
      return d->priority;
}

00119 int NameRecord::weight() const
{
      Q_ASSERT(d);
      return d->weight;
}

00125 int NameRecord::port() const
{
      Q_ASSERT(d);
      return d->port;
}

00131 QList<QByteArray> NameRecord::texts() const
{
      Q_ASSERT(d);
      return d->texts;
}

00137 QByteArray NameRecord::cpu() const
{
      Q_ASSERT(d);
      return d->cpu;
}

00143 QByteArray NameRecord::os() const
{
      Q_ASSERT(d);
      return d->os;
}

00149 QByteArray NameRecord::rawData() const
{
      Q_ASSERT(d);
      return d->rawData;
}

00155 void NameRecord::setOwner(const QByteArray &name)
{
      ENSURE_D
      d->owner = name;
}

00161 void NameRecord::setTtl(int seconds)
{
      ENSURE_D
      d->ttl = seconds;
}

00167 void NameRecord::setAddress(const QHostAddress &a)
{
      ENSURE_D
      if(a.protocol() == QAbstractSocket::IPv6Protocol)
            d->type = NameRecord::Aaaa;
      else
            d->type = NameRecord::A;
      d->address = a;
}

00177 void NameRecord::setMx(const QByteArray &name, int priority)
{
      ENSURE_D
      d->type = NameRecord::Mx;
      d->name = name;
      d->priority = priority;
}

00185 void NameRecord::setSrv(const QByteArray &name, int port, int priority, int weight)
{
      ENSURE_D
      d->type = NameRecord::Srv;
      d->name = name;
      d->port = port;
      d->priority = priority;
      d->weight = weight;
}

00195 void NameRecord::setCname(const QByteArray &name)
{
      ENSURE_D
      d->type = NameRecord::Cname;
      d->name = name;
}

00202 void NameRecord::setPtr(const QByteArray &name)
{
      ENSURE_D
      d->type = NameRecord::Ptr;
      d->name = name;
}

00209 void NameRecord::setTxt(const QList<QByteArray> &texts)
{
      ENSURE_D
      d->type = NameRecord::Txt;
      d->texts = texts;
}

00216 void NameRecord::setHinfo(const QByteArray &cpu, const QByteArray &os)
{
      ENSURE_D
      d->type = NameRecord::Hinfo;
      d->cpu = cpu;
      d->os = os;
}

00224 void NameRecord::setNs(const QByteArray &name)
{
      ENSURE_D
      d->type = NameRecord::Ns;
      d->name = name;
}

00231 void NameRecord::setNull(const QByteArray &rawData)
{
      ENSURE_D
      d->type = NameRecord::Null;
      d->rawData = rawData;
}

QDebug operator<<(QDebug dbg, XMPP::NameRecord::Type type)
{
      dbg.nospace() << "XMPP::NameRecord::";

      switch(type)
      {
            case XMPP::NameRecord::A:
                  dbg.nospace() << "A";
                  break;
            case XMPP::NameRecord::Aaaa:
                  dbg.nospace() << "Aaaa";
                  break;
            case XMPP::NameRecord::Mx:
                  dbg.nospace() << "Mx";
                  break;
            case XMPP::NameRecord::Srv:
                  dbg.nospace() << "Srv";
                  break;
            case XMPP::NameRecord::Cname:
                  dbg.nospace() << "Cname";
                  break;
            case XMPP::NameRecord::Ptr:
                  dbg.nospace() << "Ptr";
                  break;
            case XMPP::NameRecord::Txt:
                  dbg.nospace() << "Txt";
                  break;
            case XMPP::NameRecord::Hinfo:
                  dbg.nospace() << "Hinfo";
                  break;
            case XMPP::NameRecord::Ns:
                  dbg.nospace() << "Ns";
                  break;
            case XMPP::NameRecord::Null:
                  dbg.nospace() << "Null";
                  break;
            case XMPP::NameRecord::Any:
                  dbg.nospace() << "Any";
                  break;
      }

      return dbg;
}

QDebug operator<<(QDebug dbg, const XMPP::NameRecord &record)
{
      dbg.nospace() << "XMPP::NameRecord("
            << "owner=" << record.owner()
            << ", ttl=" << record.ttl()
            << ", type=" << record.type();

      switch(record.type())
      {
            case XMPP::NameRecord::A:
            case XMPP::NameRecord::Aaaa:
                  dbg.nospace() << ", address=" << record.address();
                  break;
            case XMPP::NameRecord::Mx:
                  dbg.nospace()
                        << ", name=" << record.name()
                        << ", priority=" << record.priority();
                  break;
            case XMPP::NameRecord::Srv:
                  dbg.nospace()
                        << ", name=" << record.name()
                        << ", port=" << record.port()
                        << ", priority=" << record.priority()
                        << ", weight=" << record.weight();
                  break;
            case XMPP::NameRecord::Cname:
            case XMPP::NameRecord::Ptr:
            case XMPP::NameRecord::Ns:
                  dbg.nospace() << ", name=" << record.name();
                  break;
            case XMPP::NameRecord::Txt:
                  dbg.nospace() << ", texts={" << record.texts() << "}";
                  break;
            case XMPP::NameRecord::Hinfo:
                  dbg.nospace() << ", cpu=" << record.cpu() << ", os=" << record.os();
                  break;
            case XMPP::NameRecord::Null:
                  dbg.nospace() << ", size=" << record.rawData().size();
                  break;
            case XMPP::NameRecord::Any:
                  // can't happen
                  Q_ASSERT(0);
                  break;
      }

      dbg.nospace() << ")";
      return dbg;
}

//----------------------------------------------------------------------------
// ServiceInstance
//----------------------------------------------------------------------------
00334 class ServiceInstance::Private : public QSharedData
{
public:
      QString instance, type, domain;
      QMap<QString,QByteArray> attribs;
      QByteArray name;
};

ServiceInstance::ServiceInstance()
{
      d = new Private;
}

ServiceInstance::ServiceInstance(const QString &instance, const QString &type, const QString &domain, const QMap<QString,QByteArray> &attribs)
{
      d = new Private;
      d->instance = instance;
      d->type = type;
      d->domain = domain;
      d->attribs = attribs;

      // FIXME: escape the items
      d->name = instance.toLatin1() + '.' + type.toLatin1() + '.' + domain.toLatin1();
}

ServiceInstance::ServiceInstance(const ServiceInstance &from)
{
      d = 0;
      *this = from;
}

ServiceInstance::~ServiceInstance()
{
}

ServiceInstance & ServiceInstance::operator=(const ServiceInstance &from)
{
      d = from.d;
      return *this;
}

QString ServiceInstance::instance() const
{
      return d->instance;
}

QString ServiceInstance::type() const
{
      return d->type;
}

QString ServiceInstance::domain() const
{
      return d->domain;
}

QMap<QString,QByteArray> ServiceInstance::attributes() const
{
      return d->attribs;
}

QByteArray ServiceInstance::name() const
{
      return d->name;
}

//----------------------------------------------------------------------------
// NameManager
//----------------------------------------------------------------------------
class NameManager;

Q_GLOBAL_STATIC(QMutex, nman_mutex)
static NameManager *g_nman = 0;

00408 class NameResolver::Private
{
public:
      NameResolver *q;

      int type;
      bool longLived;
      int id;

      Private(NameResolver *_q) : q(_q)
      {
      }
};

00422 class ServiceBrowser::Private
{
public:
      ServiceBrowser *q;

      int id;

      Private(ServiceBrowser *_q) : q(_q)
      {
      }
};

00434 class ServiceResolver::Private : public QObject
{
      Q_OBJECT
public:
      ServiceResolver *q;

      int id;

      int mode;
      NameResolver dns;
      AddressResolver adns;
      int port;

00447       class Server
      {
      public:
            QByteArray host;
            int port;
            int priority;
            int weight;
      };

      QList<Server> servers;
      QList<QHostAddress> addrs;

      Private(ServiceResolver *_q) : q(_q)
      {
            mode = 3;
            connect(&dns, SIGNAL(resultsReady(const QList<XMPP::NameRecord> &)), SLOT(dns_resultsReady(const QList<XMPP::NameRecord> &)));
            connect(&dns, SIGNAL(error(XMPP::NameResolver::Error)), SLOT(dns_error(XMPP::NameResolver::Error)));
            connect(&adns, SIGNAL(resultsReady(const QList<QHostAddress> &)), SLOT(adns_resultsReady(const QList<QHostAddress> &)));
            connect(&adns, SIGNAL(error(XMPP::AddressResolver::Error)), SLOT(adns_error(XMPP::AddressResolver::Error)));
      }

      void tryNext()
      {
            if(mode == 3)
            {
                  QMetaObject::invokeMethod(q, "finished", Qt::QueuedConnection);
            }
            if(mode == 2)
            {
                  if(!addrs.isEmpty())
                  {
                        QHostAddress addr = addrs.takeFirst();
                        QMetaObject::invokeMethod(q, "resultsReady", Qt::QueuedConnection, Q_ARG(QHostAddress, addr), Q_ARG(int, port));
                        return;
                  }

                  if(servers.isEmpty())
                  {
                        QMetaObject::invokeMethod(q, "finished", Qt::QueuedConnection);
                        return;
                  }

                  Server serv = servers.takeFirst();
                  port = serv.port;
                  adns.start(serv.host);
            }
            else
            {
                  if(addrs.isEmpty())
                  {
                        QMetaObject::invokeMethod(q, "finished", Qt::QueuedConnection);
                        return;
                  }

                  QHostAddress addr = addrs.takeFirst();
                  QMetaObject::invokeMethod(q, "resultsReady", Qt::QueuedConnection, Q_ARG(QHostAddress, addr), Q_ARG(int, port));
            }
      }

private slots:
      void dns_resultsReady(const QList<XMPP::NameRecord> &results)
      {
            mode = 2;
            servers.clear();
            for(int n = 0; n < results.count(); ++n)
            {
                  Server serv;
                  serv.host = results[n].name();
                  serv.port = results[n].port();
                  serv.priority = results[n].priority();
                  serv.weight = results[n].weight();
                  servers += serv;
            }
            tryNext();
      }

      void dns_error(XMPP::NameResolver::Error)
      {
            if(mode == 0 || mode == 1)
                  emit q->error();
            else
                  tryNext(); // FIXME: probably shouldn't share this
      }

      void adns_resultsReady(const QList<QHostAddress> &results)
      {
            if(mode == 1)
            {
                  addrs = results;
                  tryNext();
            }
            else
            {
                  addrs += results;
                  tryNext();
            }
      }

      void adns_error(XMPP::AddressResolver::Error)
      {
            if(mode == 0 || mode == 1)
                  emit q->error();
            else
                  tryNext(); // FIXME: probably shouldn't share this
      }
};

00554 class ServiceLocalPublisher::Private
{
public:
      ServiceLocalPublisher *q;

      int id;

      Private(ServiceLocalPublisher *_q) : q(_q)
      {
      }
};

00566 class NameManager : public QObject
{
      Q_OBJECT
public:
      NameProvider *p_net, *p_local;
      ServiceProvider *p_serv;
      QHash<int,NameResolver::Private*> res_instances;
      QHash<int,int> res_sub_instances;

      QHash<int,ServiceBrowser::Private*> br_instances;
      QHash<int,ServiceResolver::Private*> sres_instances;
      QHash<int,ServiceLocalPublisher::Private*> slp_instances;

      NameManager(QObject *parent = 0) : QObject(parent)
      {
            p_net = 0;
            p_local = 0;
            p_serv = 0;
      }

      ~NameManager()
      {
            delete p_net;
            delete p_local;
            delete p_serv;
      }

      static NameManager *instance()
      {
            QMutexLocker locker(nman_mutex());
            if(!g_nman)
            {
                  g_nman = new NameManager;
                  irisNetAddPostRoutine(NetNames::cleanup);
            }
            return g_nman;
      }

      static void cleanup()
      {
            delete g_nman;
            g_nman = 0;
      }

      void resolve_start(NameResolver::Private *np, const QByteArray &name, int qType, bool longLived)
      {
            QMutexLocker locker(nman_mutex());

            np->type = qType;
            np->longLived = longLived;
            if(!p_net)
            {
                  NameProvider *c = 0;
                  QList<IrisNetProvider*> list = irisNetProviders();
                  for(int n = 0; n < list.count(); ++n)
                  {
                        IrisNetProvider *p = list[n];
                        c = p->createNameProviderInternet();
                        if(c)
                              break;
                  }
                  Q_ASSERT(c); // we have built-in support, so this should never fail
                  p_net = c;

                  // use queued connections
                  qRegisterMetaType< QList<XMPP::NameRecord> >("QList<XMPP::NameRecord>");
                  qRegisterMetaType<XMPP::NameResolver::Error>("XMPP::NameResolver::Error");
                  connect(p_net, SIGNAL(resolve_resultsReady(int, const QList<XMPP::NameRecord> &)), SLOT(provider_resolve_resultsReady(int, const QList<XMPP::NameRecord> &)));
                  connect(p_net, SIGNAL(resolve_error(int, XMPP::NameResolver::Error)), SLOT(provider_resolve_error(int, XMPP::NameResolver::Error)));
                  connect(p_net, SIGNAL(resolve_useLocal(int, const QByteArray &)), SLOT(provider_resolve_useLocal(int, const QByteArray &)));
            }

            np->id = p_net->resolve_start(name, qType, longLived);

            //printf("assigning %d to %p\n", req_id, np);
            res_instances.insert(np->id, np);
      }

      void resolve_stop(NameResolver::Private *np)
      {
            // FIXME: stop sub instances?
            p_net->resolve_stop(np->id);
            resolve_cleanup(np);
      }

      void resolve_cleanup(NameResolver::Private *np)
      {
            res_instances.remove(np->id);
            NameResolver *q = np->q;
            delete q->d;
            q->d = 0;
      }

      void browse_start(ServiceBrowser::Private *np, const QString &type, const QString &domain)
      {
            QMutexLocker locker(nman_mutex());

            if(!p_serv)
            {
                  ServiceProvider *c = 0;
                  QList<IrisNetProvider*> list = irisNetProviders();
                  for(int n = 0; n < list.count(); ++n)
                  {
                        IrisNetProvider *p = list[n];
                        c = p->createServiceProvider();
                        if(c)
                              break;
                  }
                  Q_ASSERT(c); // we have built-in support, so this should never fail
                  p_serv = c;

                  // use queued connections
                  qRegisterMetaType<XMPP::ServiceInstance>("XMPP::ServiceInstance");
                  qRegisterMetaType<XMPP::ServiceBrowser::Error>("XMPP::ServiceBrowser::Error");

                  connect(p_serv, SIGNAL(browse_instanceAvailable(int, const XMPP::ServiceInstance &)), SLOT(provider_browse_instanceAvailable(int, const XMPP::ServiceInstance &)), Qt::QueuedConnection);
                  connect(p_serv, SIGNAL(browse_instanceUnavailable(int, const XMPP::ServiceInstance &)), SLOT(provider_browse_instanceUnavailable(int, const XMPP::ServiceInstance &)), Qt::QueuedConnection);
                  connect(p_serv, SIGNAL(browse_error(int, XMPP::ServiceBrowser::Error)), SLOT(provider_browse_error(int, XMPP::ServiceBrowser::Error)), Qt::QueuedConnection);
            }

            /*np->id = */

            np->id = p_serv->browse_start(type, domain);

            br_instances.insert(np->id, np);
      }

      void resolve_instance_start(ServiceResolver::Private *np, const QByteArray &name)
      {
            QMutexLocker locker(nman_mutex());

            if(!p_serv)
            {
                  ServiceProvider *c = 0;
                  QList<IrisNetProvider*> list = irisNetProviders();
                  for(int n = 0; n < list.count(); ++n)
                  {
                        IrisNetProvider *p = list[n];
                        c = p->createServiceProvider();
                        if(c)
                              break;
                  }
                  Q_ASSERT(c); // we have built-in support, so this should never fail
                  p_serv = c;

                  // use queued connections
                  qRegisterMetaType<QHostAddress>("QHostAddress");
                  qRegisterMetaType< QList<XMPP::ServiceProvider::ResolveResult> >("QList<XMPP::ServiceProvider::ResolveResult>");
                  connect(p_serv, SIGNAL(resolve_resultsReady(int, const QList<XMPP::ServiceProvider::ResolveResult> &)), SLOT(provider_resolve_resultsReady(int, const QList<XMPP::ServiceProvider::ResolveResult> &)), Qt::QueuedConnection);
            }

            /*np->id = */

            np->id = p_serv->resolve_start(name);

            sres_instances.insert(np->id, np);
      }

      void publish_start(ServiceLocalPublisher::Private *np, const QString &instance, const QString &type, int port, const QMap<QString,QByteArray> &attribs)
      {
            QMutexLocker locker(nman_mutex());

            if(!p_serv)
            {
                  ServiceProvider *c = 0;
                  QList<IrisNetProvider*> list = irisNetProviders();
                  for(int n = 0; n < list.count(); ++n)
                  {
                        IrisNetProvider *p = list[n];
                        c = p->createServiceProvider();
                        if(c)
                              break;
                  }
                  Q_ASSERT(c); // we have built-in support, so this should never fail
                  p_serv = c;

                  // use queued connections
                  qRegisterMetaType<XMPP::ServiceLocalPublisher::Error>("XMPP::ServiceLocalPublisher::Error");
                  connect(p_serv, SIGNAL(publish_published(int)), SLOT(provider_publish_published(int)), Qt::QueuedConnection);
                  connect(p_serv, SIGNAL(publish_extra_published(int)), SLOT(provider_publish_extra_published(int)), Qt::QueuedConnection);
            }

            /*np->id = */

            np->id = p_serv->publish_start(instance, type, port, attribs);

            slp_instances.insert(np->id, np);
      }

      void publish_extra_start(ServiceLocalPublisher::Private *np, const NameRecord &rec)
      {
            np->id = p_serv->publish_extra_start(np->id, rec);
      }

private slots:
      void provider_resolve_resultsReady(int id, const QList<XMPP::NameRecord> &results)
      {
            NameResolver::Private *np = res_instances.value(id);
            NameResolver *q = np->q; // resolve_cleanup deletes np
            if(!np->longLived)
                  resolve_cleanup(np);
            emit q->resultsReady(results);
      }

      void provider_resolve_error(int id, XMPP::NameResolver::Error e)
      {
            NameResolver::Private *np = res_instances.value(id);
            NameResolver *q = np->q; // resolve_cleanup deletes np
            resolve_cleanup(np);
            emit q->error(e);
      }

      void provider_local_resolve_resultsReady(int id, const QList<XMPP::NameRecord> &results)
      {
            int par_id = res_sub_instances.value(id);
            NameResolver::Private *np = res_instances.value(par_id);
            if(!np->longLived)
                  res_sub_instances.remove(id);
            p_net->resolve_localResultsReady(par_id, results);
      }

      void provider_local_resolve_error(int id, XMPP::NameResolver::Error e)
      {
            int par_id = res_sub_instances.value(id);
            res_sub_instances.remove(id);
            p_net->resolve_localError(par_id, e);
      }

      void provider_resolve_useLocal(int id, const QByteArray &name)
      {
            // transfer to local
            if(!p_local)
            {
                  NameProvider *c = 0;
                  QList<IrisNetProvider*> list = irisNetProviders();
                  for(int n = 0; n < list.count(); ++n)
                  {
                        IrisNetProvider *p = list[n];
                        c = p->createNameProviderLocal();
                        if(c)
                              break;
                  }
                  Q_ASSERT(c); // we have built-in support, so this should never fail
                  // FIXME: not true, binding can fail
                  p_local = c;

                  // use queued connections
                  qRegisterMetaType< QList<XMPP::NameRecord> >("QList<XMPP::NameRecord>");
                  qRegisterMetaType<XMPP::NameResolver::Error>("XMPP::NameResolver::Error");
                  connect(p_local, SIGNAL(resolve_resultsReady(int, const QList<XMPP::NameRecord> &)), SLOT(provider_local_resolve_resultsReady(int, const QList<XMPP::NameRecord> &)), Qt::QueuedConnection);
                  connect(p_local, SIGNAL(resolve_error(int, XMPP::NameResolver::Error)), SLOT(provider_local_resolve_error(int, XMPP::NameResolver::Error)), Qt::QueuedConnection);
            }

            NameResolver::Private *np = res_instances.value(id);

            /*// transfer to local only
            if(np->longLived)
            {
                  res_instances.remove(np->id);

                  np->id = p_local->resolve_start(name, np->type, true);
                  res_instances.insert(np->id, np);
            }
            // sub request
            else
            {
                  int req_id = p_local->resolve_start(name, np->type, false);

                  res_sub_instances.insert(req_id, np->id);
            }*/

            int req_id = p_local->resolve_start(name, np->type, np->longLived);
            res_sub_instances.insert(req_id, np->id);
      }

      void provider_browse_instanceAvailable(int id, const XMPP::ServiceInstance &i)
      {
            ServiceBrowser::Private *np = br_instances.value(id);
            emit np->q->instanceAvailable(i);
      }

      void provider_browse_instanceUnavailable(int id, const XMPP::ServiceInstance &i)
      {
            ServiceBrowser::Private *np = br_instances.value(id);
            emit np->q->instanceUnavailable(i);
      }

      void provider_browse_error(int id, XMPP::ServiceBrowser::Error e)
      {
            Q_UNUSED(e);
            ServiceBrowser::Private *np = br_instances.value(id);
            // TODO
            emit np->q->error();
      }

      void provider_resolve_resultsReady(int id, const QList<XMPP::ServiceProvider::ResolveResult> &results)
      {
            ServiceResolver::Private *np = sres_instances.value(id);
            emit np->q->resultsReady(results[0].address, results[0].port);
      }

      void provider_publish_published(int id)
      {
            ServiceLocalPublisher::Private *np = slp_instances.value(id);
            emit np->q->published();
      }

      void provider_publish_extra_published(int id)
      {
            Q_UNUSED(id);
            //ServiceLocalPublisher::Private *np = slp_instances.value(id);
            //emit np->q->published();
      }
};

//----------------------------------------------------------------------------
// NameResolver
//----------------------------------------------------------------------------

// copied from JDNS
#define JDNS_RTYPE_A         1
#define JDNS_RTYPE_AAAA     28
#define JDNS_RTYPE_MX       15
#define JDNS_RTYPE_SRV      33
#define JDNS_RTYPE_CNAME     5
#define JDNS_RTYPE_PTR      12
#define JDNS_RTYPE_TXT      16
#define JDNS_RTYPE_HINFO    13
#define JDNS_RTYPE_NS        2
#define JDNS_RTYPE_ANY     255

static int recordType2Rtype(NameRecord::Type type)
{
      switch(type)
      {
            case NameRecord::A:     return JDNS_RTYPE_A;
            case NameRecord::Aaaa:  return JDNS_RTYPE_AAAA;
            case NameRecord::Mx:    return JDNS_RTYPE_MX;
            case NameRecord::Srv:   return JDNS_RTYPE_SRV;
            case NameRecord::Cname: return JDNS_RTYPE_CNAME;
            case NameRecord::Ptr:   return JDNS_RTYPE_PTR;
            case NameRecord::Txt:   return JDNS_RTYPE_TXT;
            case NameRecord::Hinfo: return JDNS_RTYPE_HINFO;
            case NameRecord::Ns:    return JDNS_RTYPE_NS;
            case NameRecord::Null:  return 10;
            case NameRecord::Any:   return JDNS_RTYPE_ANY;
      }
      return -1;
}

00916 NameResolver::NameResolver(QObject *parent)
:QObject(parent)
{
      d = 0;
}

00922 NameResolver::~NameResolver()
{
      stop();
}

00927 void NameResolver::start(const QByteArray &name, NameRecord::Type type, Mode mode)
{
      stop();
      d = new Private(this);
      int qType = recordType2Rtype(type);
      if(qType == -1)
            qType = JDNS_RTYPE_A;
      NameManager::instance()->resolve_start(d, name, qType, mode == NameResolver::LongLived ? true : false);
}

00937 void NameResolver::stop()
{
      if(d)
      {
            NameManager::instance()->resolve_stop(d);
            delete d;
            d = 0;
      }
}

QDebug operator<<(QDebug dbg, XMPP::NameResolver::Error e)
{
      dbg.nospace() << "XMPP::NameResolver::";

      switch(e)
      {
            case XMPP::NameResolver::ErrorGeneric:
                  dbg.nospace() << "ErrorGeneric";
                  break;
            case XMPP::NameResolver::ErrorNoName:
                  dbg.nospace() << "ErrorNoName";
                  break;
            case XMPP::NameResolver::ErrorTimeout:
                  dbg.nospace() << "ErrorTimeout";
                  break;
            case XMPP::NameResolver::ErrorNoLocal:
                  dbg.nospace() << "ErrorNoLocal";
                  break;
            case XMPP::NameResolver::ErrorNoLongLived:
                  dbg.nospace() << "ErrorNoLongLived";
                  break;
      }

      return dbg;
}

//----------------------------------------------------------------------------
// ServiceBrowser
//----------------------------------------------------------------------------
ServiceBrowser::ServiceBrowser(QObject *parent)
:QObject(parent)
{
      d = new Private(this);
}

ServiceBrowser::~ServiceBrowser()
{
      delete d;
}

void ServiceBrowser::start(const QString &type, const QString &domain)
{
      NameManager::instance()->browse_start(d, type, domain);
}

void ServiceBrowser::stop()
{
}

//----------------------------------------------------------------------------
// ServiceResolver
//----------------------------------------------------------------------------
ServiceResolver::ServiceResolver(QObject *parent)
:QObject(parent)
{
      qRegisterMetaType<QHostAddress>("QHostAddress");
      d = new Private(this);
}

ServiceResolver::~ServiceResolver()
{
      delete d;
}

void ServiceResolver::startFromInstance(const QByteArray &name)
{
      NameManager::instance()->resolve_instance_start(d, name);
}

void ServiceResolver::startFromDomain(const QString &domain, const QString &type)
{
      d->mode = 0;
      d->dns.start(type.toLatin1() + '.' + domain.toLatin1(), NameRecord::Srv);
}

void ServiceResolver::startFromPlain(const QString &host, int port)
{
      d->mode = 1;
      d->port = port;
      d->adns.start(host.toLatin1());
}

void ServiceResolver::tryNext()
{
      d->tryNext();
}

void ServiceResolver::stop()
{
}

//----------------------------------------------------------------------------
// ServiceLocalPublisher
//----------------------------------------------------------------------------
ServiceLocalPublisher::ServiceLocalPublisher(QObject *parent)
:QObject(parent)
{
      d = new Private(this);
}

ServiceLocalPublisher::~ServiceLocalPublisher()
{
      delete d;
}

void ServiceLocalPublisher::publish(const QString &instance, const QString &type, int port, const QMap<QString,QByteArray> &attributes)
{
      NameManager::instance()->publish_start(d, instance, type, port, attributes);
}

void ServiceLocalPublisher::updateAttributes(const QMap<QString,QByteArray> &attributes)
{
      Q_UNUSED(attributes);
}

void ServiceLocalPublisher::addRecord(const NameRecord &rec)
{
      NameManager::instance()->publish_extra_start(d, rec);
}

void ServiceLocalPublisher::cancel()
{
}

//----------------------------------------------------------------------------
// NetNames
//----------------------------------------------------------------------------
void NetNames::cleanup()
{
      NameManager::cleanup();
}

QString NetNames::diagnosticText()
{
      // TODO
      return QString();
}

QByteArray NetNames::idnaFromString(const QString &in)
{
      // TODO
      Q_UNUSED(in);
      return QByteArray();
}

QString NetNames::idnaToString(const QByteArray &in)
{
      // TODO
      Q_UNUSED(in);
      return QString();
}

QByteArray NetNames::escapeDomain(const QByteArray &in)
{
      // TODO
      Q_UNUSED(in);
      return QByteArray();
}

QByteArray NetNames::unescapeDomain(const QByteArray &in)
{
      // TODO
      Q_UNUSED(in);
      return QByteArray();
}

}

#include "netnames.moc"

Generated by  Doxygen 1.6.0   Back to index