diff options
| author | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-08-29 13:52:52 +0000 |
|---|---|---|
| committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-08-29 13:52:52 +0000 |
| commit | 851354149e4d26237b2c45f48978b34c23097c6b (patch) | |
| tree | 7eaff7aa10b44e765b32e9c43758a57070fa344c /src | |
| parent | 1dda2e3834621a6ecda6295bb19993aff4efbac6 (diff) | |
| download | qxmpp-851354149e4d26237b2c45f48978b34c23097c6b.tar.gz | |
add QXmppServiceInfo for DNS SRV lookups
Diffstat (limited to 'src')
| -rw-r--r-- | src/QXmppServiceInfo.cpp | 171 | ||||
| -rw-r--r-- | src/QXmppServiceInfo.h | 49 | ||||
| -rw-r--r-- | src/src.pro | 2 |
3 files changed, 222 insertions, 0 deletions
diff --git a/src/QXmppServiceInfo.cpp b/src/QXmppServiceInfo.cpp new file mode 100644 index 00000000..3125709b --- /dev/null +++ b/src/QXmppServiceInfo.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2008-2010 The QXmpp developers + * + * Author: + * Jeremy Lainé + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * 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. + * + */ + +#include <QDebug> + +#include "QXmppServiceInfo.h" + +#ifdef Q_OS_WIN +#include <windows.h> +#include <windns.h> +#else +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/nameser.h> +#include <arpa/nameser_compat.h> +#include <resolv.h> +#endif + +QString QXmppServiceInfo::hostName() const +{ + return host_name; +} + +quint16 QXmppServiceInfo::port() const +{ + return host_port; +} + +void QXmppServiceInfo::setHostName(const QString &hostName) +{ + host_name = hostName; +} + +void QXmppServiceInfo::setPort(quint16 port) +{ + host_port = port; +} + +/// Perform a DNS lookup for an SRV entry. +/// +/// Returns true if the lookup was succesful, false if it failed. +/// +/// \param dname +/// \param results + +bool QXmppServiceInfo::lookupService(const QString &dname, QList<QXmppServiceInfo> &results) +{ +#ifdef Q_OS_WIN + PDNS_RECORD records, ptr; + + /* perform DNS query */ + if (DnsQuery_UTF8(dname.toAscii(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &records, NULL) != ERROR_SUCCESS) + { + qWarning() << "SRV lookup for" << dname << "failed"; + return false; + } + + /* extract results */ + for (ptr = records; ptr != NULL; ptr = ptr->pNext) + { + if ((ptr->wType == DNS_TYPE_SRV) && !strcmp(ptr->pName, dname.toAscii())) + { + QXmppServiceInfo info; + info.setHostName(ptr->Data.Srv.pNameTarget); + info.setPort(ptr->Data.Srv.wPort); + results.append(info); + } + } + + DnsRecordListFree(records, DnsFreeRecordList); +#else + unsigned char response[PACKETSZ]; + int responseLength, answerCount, answerIndex; + + /* explicitly call res_init in case config changed */ + res_init(); + + /* perform DNS query */ + memset(response, 0, sizeof(response)); + responseLength = res_query(dname.toAscii(), C_IN, T_SRV, response, sizeof(response)); + if (responseLength < int(sizeof(HEADER))) + { + qWarning() << "SRV lookup for" << dname << "failed"; + herror("SRV lookup error"); + return false; + } + + /* check the response header */ + HEADER *header = (HEADER*)response; + if (header->rcode != NOERROR || !(answerCount = ntohs(header->ancount))) + { + qWarning() << "SRV lookup for" << dname << "returned an error"; + return false; + } + + /* skip the query */ + char host[PACKETSZ], answer[PACKETSZ]; + unsigned char *p = response + sizeof(HEADER); + int status = dn_expand(response, response + responseLength, p, host, sizeof(host)); + if (status < 0) + { + qWarning("dn_expand failed"); + return false; + } + p += status + 4; + + /* parse answers */ + answerIndex = 0; + while ((p < response + responseLength) && (answerIndex < answerCount)) + { + int type, klass, ttl, size; + status = dn_expand(response, response + responseLength, p, host, sizeof(host)); + if (status < 0) + { + qWarning("dn_expand failed"); + return false; + } + + p += status; + type = (p[0] << 8) | p[1]; + p += 2; + klass = (p[0] << 8) | p[1]; + p += 2; + ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + p += 4; + size = (p[0] << 8) | p[1]; + p += 2; + + if (type == T_SRV) + { + quint16 port = (p[4] << 8) | p[5]; + status = dn_expand(response, response + responseLength, p + 6, answer, sizeof(answer)); + if (status < 0) + { + qWarning("dn_expand failed"); + return false; + } + QXmppServiceInfo info; + info.setHostName(answer); + info.setPort(port); + results.append(info); + } else { + qWarning("Unexpected DNS answer type"); + } + p += size; + answerIndex++; + } +#endif + return !results.isEmpty(); +} diff --git a/src/QXmppServiceInfo.h b/src/QXmppServiceInfo.h new file mode 100644 index 00000000..a007e427 --- /dev/null +++ b/src/QXmppServiceInfo.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008-2010 The QXmpp developers + * + * Author: + * Jeremy Lainé + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * 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. + * + */ + +#ifndef QXMPPSERVICEINFO_H +#define QXMPPSERVICEINFO_H + +#include <QList> +#include <QString> + +/// \brief The QXmppServiceInfo class is used to perform DNS SRV queries. +/// + +class QXmppServiceInfo +{ +public: + QString hostName() const; + void setHostName(const QString &hostName); + + quint16 port() const; + void setPort(quint16 port); + + static bool lookupService(const QString &dname, QList<QXmppServiceInfo> &results); + +private: + QString host_name; + quint16 host_port; +}; + +#endif diff --git a/src/src.pro b/src/src.pro index 40c8c089..edd2700d 100644 --- a/src/src.pro +++ b/src/src.pro @@ -55,6 +55,7 @@ INSTALL_HEADERS = QXmppUtils.h \ QXmppServer.h \ QXmppServerExtension.h \ QXmppServerPlugin.h \ + QXmppServiceInfo.h \ QXmppSessionIq.h \ QXmppSocks.h \ QXmppStanza.h \ @@ -107,6 +108,7 @@ SOURCES += QXmppUtils.cpp \ QXmppSaslAuth.cpp \ QXmppServer.cpp \ QXmppServerExtension.cpp \ + QXmppServiceInfo.cpp \ QXmppSessionIq.cpp \ QXmppSocks.cpp \ QXmppStanza.cpp \ |
