initial commit

This commit is contained in:
mikhail "synzr" 2025-12-25 01:37:49 +05:00
commit 9d20827c46
2469 changed files with 470994 additions and 0 deletions

View file

@ -0,0 +1,13 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/safedelete.h \
$$PWD/ndns.h \
$$PWD/srvresolver.h \
$$PWD/servsock.h
SOURCES += \
$$PWD/safedelete.cpp \
$$PWD/ndns.cpp \
$$PWD/srvresolver.cpp \
$$PWD/servsock.cpp

View file

@ -0,0 +1,147 @@
/*
* ndns.cpp - native DNS resolution
* Copyright (C) 2001, 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
//! \class NDns ndns.h
//! \brief Simple DNS resolution using native system calls
//!
//! This class is to be used when Qt's QDns is not good enough. Because QDns
//! does not use threads, it cannot make a system call asyncronously. Thus,
//! QDns tries to imitate the behavior of each platform's native behavior, and
//! generally falls short.
//!
//! NDns uses a thread to make the system call happen in the background. This
//! gives your program native DNS behavior, at the cost of requiring threads
//! to build.
//!
//! \code
//! #include "ndns.h"
//!
//! ...
//!
//! NDns dns;
//! dns.resolve("psi.affinix.com");
//!
//! // The class will emit the resultsReady() signal when the resolution
//! // is finished. You may then retrieve the results:
//!
//! QHostAddress ip_address = dns.result();
//!
//! // or if you want to get the IP address as a string:
//!
//! QString ip_address = dns.resultString();
//! \endcode
#include "ndns.h"
#include "netnames.h"
// CS_NAMESPACE_BEGIN
//----------------------------------------------------------------------------
// NDns
//----------------------------------------------------------------------------
//! \fn void NDns::resultsReady()
//! This signal is emitted when the DNS resolution succeeds or fails.
//!
//! Constructs an NDns object with parent \a parent.
NDns::NDns(QObject *parent)
:QObject(parent)
{
busy = false;
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)));
}
//!
//! Destroys the object and frees allocated resources.
NDns::~NDns()
{
stop();
}
//!
//! Resolves hostname \a host (eg. psi.affinix.com)
void NDns::resolve(const QString &host)
{
QHostAddress a;
if (a.setAddress(host)) {
addr = a;
QMetaObject::invokeMethod(this, "resultsReady", Qt::QueuedConnection);
}
else {
stop();
busy = true;
dns.start(host.toLatin1());
}
}
//!
//! Cancels the lookup action.
//! \note This will not stop the underlying system call, which must finish before the next lookup will proceed.
void NDns::stop()
{
dns.stop();
busy = false;
}
//!
//! Returns the IP address as QHostAddress. This will be a Null QHostAddress if the lookup failed.
//! \sa resultsReady()
QHostAddress NDns::result() const
{
return addr;
}
//!
//! Returns the IP address as a string. This will be an empty string if the lookup failed.
//! \sa resultsReady()
QString NDns::resultString() const
{
if (addr.isNull())
return QString();
else
return addr.toString();
}
//!
//! Returns TRUE if busy resolving a hostname.
bool NDns::isBusy() const
{
return busy;
}
void NDns::dns_resultsReady(const QList<XMPP::NameRecord> &results)
{
addr = results[0].address();
busy = false;
emit resultsReady();
}
void NDns::dns_error(XMPP::NameResolver::Error)
{
addr = QHostAddress();
busy = false;
emit resultsReady();
}
// CS_NAMESPACE_END

View file

@ -0,0 +1,59 @@
/*
* ndns.h - native DNS resolution
* Copyright (C) 2001, 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef CS_NDNS_H
#define CS_NDNS_H
#include <QtCore>
#include <QtNetwork>
#include "netnames.h"
// CS_NAMESPACE_BEGIN
class NDns : public QObject
{
Q_OBJECT
public:
NDns(QObject *parent=0);
~NDns();
void resolve(const QString &);
void stop();
bool isBusy() const;
QHostAddress result() const;
QString resultString() const;
signals:
void resultsReady();
private slots:
void dns_resultsReady(const QList<XMPP::NameRecord> &);
void dns_error(XMPP::NameResolver::Error);
private:
XMPP::NameResolver dns;
bool busy;
QHostAddress addr;
};
// CS_NAMESPACE_END
#endif

View file

@ -0,0 +1,114 @@
#include"safedelete.h"
//----------------------------------------------------------------------------
// SafeDelete
//----------------------------------------------------------------------------
SafeDelete::SafeDelete()
{
lock = 0;
}
SafeDelete::~SafeDelete()
{
if(lock)
lock->dying();
}
void SafeDelete::deleteLater(QObject *o)
{
if(!lock)
deleteSingle(o);
else
list.append(o);
}
void SafeDelete::unlock()
{
lock = 0;
deleteAll();
}
void SafeDelete::deleteAll()
{
if(list.isEmpty())
return;
for(int n = 0; n < list.size(); ++n)
deleteSingle(list[n]);
list.clear();
}
void SafeDelete::deleteSingle(QObject *o)
{
#if QT_VERSION < 0x030000
// roll our own QObject::deleteLater()
SafeDeleteLater *sdl = SafeDeleteLater::ensureExists();
sdl->deleteItLater(o);
#else
o->deleteLater();
#endif
}
//----------------------------------------------------------------------------
// SafeDeleteLock
//----------------------------------------------------------------------------
SafeDeleteLock::SafeDeleteLock(SafeDelete *sd)
{
own = false;
if(!sd->lock) {
_sd = sd;
_sd->lock = this;
}
else
_sd = 0;
}
SafeDeleteLock::~SafeDeleteLock()
{
if(_sd) {
_sd->unlock();
if(own)
delete _sd;
}
}
void SafeDeleteLock::dying()
{
_sd = new SafeDelete(*_sd);
own = true;
}
//----------------------------------------------------------------------------
// SafeDeleteLater
//----------------------------------------------------------------------------
SafeDeleteLater *SafeDeleteLater::self = 0;
SafeDeleteLater *SafeDeleteLater::ensureExists()
{
if(!self)
new SafeDeleteLater();
return self;
}
SafeDeleteLater::SafeDeleteLater()
{
self = this;
QTimer::singleShot(0, this, SLOT(explode()));
}
SafeDeleteLater::~SafeDeleteLater()
{
qDeleteAll(list);
list.clear();
self = 0;
}
void SafeDeleteLater::deleteItLater(QObject *o)
{
list.append(o);
}
void SafeDeleteLater::explode()
{
delete this;
}

View file

@ -0,0 +1,59 @@
#ifndef SAFEDELETE_H
#define SAFEDELETE_H
#include <QtCore>
class SafeDelete;
class SafeDeleteLock
{
public:
SafeDeleteLock(SafeDelete *sd);
~SafeDeleteLock();
private:
SafeDelete *_sd;
bool own;
friend class SafeDelete;
void dying();
};
class SafeDelete
{
public:
SafeDelete();
~SafeDelete();
void deleteLater(QObject *o);
// same as QObject::deleteLater()
static void deleteSingle(QObject *o);
private:
QObjectList list;
void deleteAll();
friend class SafeDeleteLock;
SafeDeleteLock *lock;
void unlock();
};
class SafeDeleteLater : public QObject
{
Q_OBJECT
public:
static SafeDeleteLater *ensureExists();
void deleteItLater(QObject *o);
private slots:
void explode();
private:
SafeDeleteLater();
~SafeDeleteLater();
QObjectList list;
friend class SafeDelete;
static SafeDeleteLater *self;
};
#endif

View file

@ -0,0 +1,111 @@
/*
* servsock.cpp - simple wrapper to QServerSocket
* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "servsock.h"
// CS_NAMESPACE_BEGIN
//----------------------------------------------------------------------------
// ServSock
//----------------------------------------------------------------------------
class ServSock::Private
{
public:
Private() {}
ServSockSignal *serv;
};
ServSock::ServSock(QObject *parent)
:QObject(parent)
{
d = new Private;
d->serv = 0;
}
ServSock::~ServSock()
{
stop();
delete d;
}
bool ServSock::isActive() const
{
return (d->serv ? true: false);
}
bool ServSock::listen(quint16 port)
{
stop();
d->serv = new ServSockSignal(this);
if(!d->serv->listen(QHostAddress::Any, port)) {
delete d->serv;
d->serv = 0;
return false;
}
connect(d->serv, SIGNAL(connectionReady(int)), SLOT(sss_connectionReady(int)));
return true;
}
void ServSock::stop()
{
delete d->serv;
d->serv = 0;
}
int ServSock::port() const
{
if(d->serv)
return d->serv->serverPort();
else
return -1;
}
QHostAddress ServSock::address() const
{
if(d->serv)
return d->serv->serverAddress();
else
return QHostAddress();
}
void ServSock::sss_connectionReady(int s)
{
connectionReady(s);
}
//----------------------------------------------------------------------------
// ServSockSignal
//----------------------------------------------------------------------------
ServSockSignal::ServSockSignal(QObject *parent)
:QTcpServer(parent)
{
setMaxPendingConnections(16);
}
void ServSockSignal::incomingConnection(int socketDescriptor)
{
connectionReady(socketDescriptor);
}
// CS_NAMESPACE_END

View file

@ -0,0 +1,68 @@
/*
* servsock.h - simple wrapper to QServerSocket
* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef CS_SERVSOCK_H
#define CS_SERVSOCK_H
#include <QTcpServer>
// CS_NAMESPACE_BEGIN
class ServSock : public QObject
{
Q_OBJECT
public:
ServSock(QObject *parent=0);
~ServSock();
bool isActive() const;
bool listen(quint16 port);
void stop();
int port() const;
QHostAddress address() const;
signals:
void connectionReady(int);
private slots:
void sss_connectionReady(int);
private:
class Private;
Private *d;
};
class ServSockSignal : public QTcpServer
{
Q_OBJECT
public:
ServSockSignal(QObject *parent = 0);
signals:
void connectionReady(int);
protected:
// reimplemented
void incomingConnection(int socketDescriptor);
};
// CS_NAMESPACE_END
#endif

View file

@ -0,0 +1,298 @@
/*
* srvresolver.cpp - class to simplify SRV lookups
* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "srvresolver.h"
#include <QtAlgorithms>
#ifndef NO_NDNS
# include "ndns.h"
#endif
// CS_NAMESPACE_BEGIN
bool serverLessThan(const Q3Dns::Server &s1, const Q3Dns::Server &s2)
{
int a = s1.priority;
int b = s2.priority;
int j = s1.weight;
int k = s2.weight;
return a < b || (a == b && j < k);
}
static void sortSRVList(QList<Q3Dns::Server> &list)
{
qStableSort(list.begin(), list.end(), serverLessThan);
}
class SrvResolver::Private
{
public:
Private() {}
XMPP::NameResolver nndns;
XMPP::NameRecord::Type nntype;
bool nndns_busy;
#ifndef NO_NDNS
NDns ndns;
#endif
bool failed;
QHostAddress resultAddress;
quint16 resultPort;
bool srvonly;
QString srv;
QList<Q3Dns::Server> servers;
bool aaaa;
QTimer t;
};
SrvResolver::SrvResolver(QObject *parent)
:QObject(parent)
{
d = new Private;
d->nndns_busy = false;
connect(&d->nndns, SIGNAL(resultsReady(const QList<XMPP::NameRecord> &)), SLOT(nndns_resultsReady(const QList<XMPP::NameRecord> &)));
connect(&d->nndns, SIGNAL(error(XMPP::NameResolver::Error)), SLOT(nndns_error(XMPP::NameResolver::Error)));
#ifndef NO_NDNS
connect(&d->ndns, SIGNAL(resultsReady()), SLOT(ndns_done()));
#endif
connect(&d->t, SIGNAL(timeout()), SLOT(t_timeout()));
stop();
}
SrvResolver::~SrvResolver()
{
stop();
delete d;
}
void SrvResolver::resolve(const QString &server, const QString &type, const QString &proto, bool srvOnly)
{
stop();
d->failed = false;
d->srvonly = srvOnly;
d->srv = QString("_") + type + "._" + proto + '.' + server;
d->t.setSingleShot(true);
d->t.start(15000);
d->nndns_busy = true;
d->nntype = XMPP::NameRecord::Srv;
d->nndns.start(d->srv.toLatin1(), d->nntype);
}
void SrvResolver::resolve(const QString &server, const QString &type, const QString &proto)
{
resolve(server, type, proto, false);
}
void SrvResolver::resolveSrvOnly(const QString &server, const QString &type, const QString &proto)
{
resolve(server, type, proto, true);
}
void SrvResolver::next()
{
if(d->servers.isEmpty())
return;
tryNext();
}
void SrvResolver::stop()
{
if(d->t.isActive())
d->t.stop();
if(d->nndns_busy) {
d->nndns.stop();
d->nndns_busy = false;
}
#ifndef NO_NDNS
if(d->ndns.isBusy())
d->ndns.stop();
#endif
d->resultAddress = QHostAddress();
d->resultPort = 0;
d->servers.clear();
d->srv = "";
d->failed = true;
}
bool SrvResolver::isBusy() const
{
#ifndef NO_NDNS
if(d->nndns_busy || d->ndns.isBusy())
#else
if(d->nndns_busy)
#endif
return true;
else
return false;
}
QList<Q3Dns::Server> SrvResolver::servers() const
{
return d->servers;
}
bool SrvResolver::failed() const
{
return d->failed;
}
QHostAddress SrvResolver::resultAddress() const
{
return d->resultAddress;
}
quint16 SrvResolver::resultPort() const
{
return d->resultPort;
}
void SrvResolver::tryNext()
{
#ifndef NO_NDNS
d->ndns.resolve(d->servers.first().name);
#else
d->nndns_busy = true;
d->nntype = d->aaaa ? XMPP::NameRecord::Aaaa : XMPP::NameRecord::A;
d->nndns.start(d->servers.first().name.toLatin1(), d->nntype);
#endif
}
void SrvResolver::nndns_resultsReady(const QList<XMPP::NameRecord> &results)
{
if(!d->nndns_busy)
return;
d->t.stop();
if(d->nntype == XMPP::NameRecord::Srv) {
// grab the server list and destroy the qdns object
QList<Q3Dns::Server> list;
for(int n = 0; n < results.count(); ++n)
{
list += Q3Dns::Server(QString::fromLatin1(results[n].name()), results[n].priority(), results[n].weight(), results[n].port());
}
d->nndns_busy = false;
d->nndns.stop();
if(list.isEmpty()) {
stop();
resultsReady();
return;
}
sortSRVList(list);
d->servers = list;
if(d->srvonly)
resultsReady();
else {
// kick it off
d->aaaa = true;
tryNext();
}
}
else {
// grab the address list and destroy the qdns object
QList<QHostAddress> list;
if(d->nntype == XMPP::NameRecord::A || d->nntype == XMPP::NameRecord::Aaaa)
{
for(int n = 0; n < results.count(); ++n)
{
list += results[n].address();
}
}
d->nndns_busy = false;
d->nndns.stop();
if(!list.isEmpty()) {
int port = d->servers.first().port;
d->servers.removeFirst();
d->aaaa = true;
d->resultAddress = list.first();
d->resultPort = port;
resultsReady();
}
else {
if(!d->aaaa)
d->servers.removeFirst();
d->aaaa = !d->aaaa;
// failed? bail if last one
if(d->servers.isEmpty()) {
stop();
resultsReady();
return;
}
// otherwise try the next
tryNext();
}
}
}
void SrvResolver::nndns_error(XMPP::NameResolver::Error)
{
nndns_resultsReady(QList<XMPP::NameRecord>());
}
void SrvResolver::ndns_done()
{
#ifndef NO_NDNS
QHostAddress r = d->ndns.result();
int port = d->servers.first().port;
d->servers.removeFirst();
if(!r.isNull()) {
d->resultAddress = r;
d->resultPort = port;
resultsReady();
}
else {
// failed? bail if last one
if(d->servers.isEmpty()) {
stop();
resultsReady();
return;
}
// otherwise try the next
tryNext();
}
#endif
}
void SrvResolver::t_timeout()
{
stop();
resultsReady();
}
// CS_NAMESPACE_END

View file

@ -0,0 +1,87 @@
/*
* srvresolver.h - class to simplify SRV lookups
* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef CS_SRVRESOLVER_H
#define CS_SRVRESOLVER_H
#include <QtCore>
#include <QtNetwork>
#include "netnames.h"
// CS_NAMESPACE_BEGIN
class INQ3Dns
{
public:
class Server
{
public:
Server(const QString &n = QString(), quint16 p = 0, quint16 w = 0, quint16 po = 0)
:name(n), priority(p), weight(w), port(po) {}
QString name;
quint16 priority;
quint16 weight;
quint16 port;
};
};
#define Q3Dns INQ3Dns
class SrvResolver : public QObject
{
Q_OBJECT
public:
SrvResolver(QObject *parent=0);
~SrvResolver();
void resolve(const QString &server, const QString &type, const QString &proto);
void resolveSrvOnly(const QString &server, const QString &type, const QString &proto);
void next();
void stop();
bool isBusy() const;
QList<Q3Dns::Server> servers() const;
bool failed() const;
QHostAddress resultAddress() const;
quint16 resultPort() const;
signals:
void resultsReady();
private slots:
void nndns_resultsReady(const QList<XMPP::NameRecord> &);
void nndns_error(XMPP::NameResolver::Error);
void ndns_done();
void t_timeout();
private:
class Private;
Private *d;
void tryNext();
void resolve(const QString &server, const QString &type, const QString &proto, bool srvOnly);
};
// CS_NAMESPACE_END
#endif