File indexing completed on 2024-04-14 14:19:50

0001 /*  -*- C++ -*-
0002  *  Copyright (C) 2003 Thiago Macieira <thiago@kde.org>
0003  *
0004  *
0005  *  Permission is hereby granted, free of charge, to any person obtaining
0006  *  a copy of this software and associated documentation files (the
0007  *  "Software"), to deal in the Software without restriction, including
0008  *  without limitation the rights to use, copy, modify, merge, publish,
0009  *  distribute, sublicense, and/or sell copies of the Software, and to
0010  *  permit persons to whom the Software is furnished to do so, subject to
0011  *  the following conditions:
0012  *
0013  *  The above copyright notice and this permission notice shall be included
0014  *  in all copies or substantial portions of the Software.
0015  *
0016  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0017  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0018  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0019  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
0020  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
0021  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
0022  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0023  */
0024 
0025 #include "k3reverseresolver.h"
0026 
0027 #include <config-network.h>
0028 
0029 // System includes
0030 #include <sys/types.h>
0031 #include <sys/socket.h>
0032 #include <netdb.h>
0033 #include <signal.h>
0034 
0035 // Qt
0036 #include <QEvent>
0037 #include <QMutex>
0038 #include <QCoreApplication>
0039 
0040 // Us
0041 #include "k3resolver_p.h"
0042 #include "k3resolverworkerbase.h"
0043 
0044 #if !HAVE_GETNAMEINFO
0045 // FIXME KDE4:
0046 // move to syssocket or adapt
0047 # include "netsupp.h"
0048 #endif
0049 
0050 using namespace KNetwork;
0051 using namespace KNetwork::Internal;
0052 
0053 namespace
0054 {
0055 class ReverseThread: public KResolverWorkerBase
0056 {
0057 public:
0058     ReverseThread(const KSocketAddress &addr, int flags)
0059         : m_addr(addr), m_flags(flags), m_parent(nullptr)
0060     { }
0061 
0062     ~ReverseThread() override
0063     { }
0064 
0065     bool preprocess() override
0066     {
0067         return true;
0068     }
0069     bool run() override;
0070     bool postprocess() override;
0071 
0072     // input:
0073     KSocketAddress m_addr;
0074     int m_flags;
0075     KReverseResolver *m_parent;
0076 
0077     // output:
0078     QString node;
0079     QString service;
0080     bool success;
0081 };
0082 
0083 class KReverseResolverEvent: public QEvent
0084 {
0085 public:
0086     static const int myType = QEvent::User + 63; // arbitrary value
0087     QString node;
0088     QString service;
0089     bool success;
0090 
0091     KReverseResolverEvent(const QString &_node, const QString &_service,
0092                           bool _success)
0093         : QEvent((Type)myType), node(_node),
0094           service(_service), success(_success)
0095     { }
0096 };
0097 }
0098 
0099 class KNetwork::KReverseResolverPrivate
0100 {
0101 public:
0102     QString node;
0103     QString service;
0104     KSocketAddress addr;
0105     int flags;
0106 
0107     ReverseThread *worker;
0108     bool success;
0109 
0110     inline KReverseResolverPrivate(const KSocketAddress &_addr)
0111         : addr(_addr), worker(nullptr), success(false)
0112     { }
0113 };
0114 
0115 KReverseResolver::KReverseResolver(const KSocketAddress &addr, int flags,
0116                                    QObject *parent)
0117     : QObject(parent), d(new KReverseResolverPrivate(addr))
0118 {
0119     d->flags = flags;
0120 }
0121 
0122 KReverseResolver::~KReverseResolver()
0123 {
0124     if (d->worker) {
0125         d->worker->m_parent = nullptr;
0126     }
0127     delete d;
0128 }
0129 
0130 bool KReverseResolver::isRunning() const
0131 {
0132     return d->worker != nullptr;
0133 }
0134 
0135 bool KReverseResolver::success() const
0136 {
0137     return !isRunning() && d->success;
0138 }
0139 
0140 bool KReverseResolver::failure() const
0141 {
0142     return !isRunning() && !d->success;
0143 }
0144 
0145 QString KReverseResolver::node() const
0146 {
0147     return d->node;
0148 }
0149 
0150 QString KReverseResolver::service() const
0151 {
0152     return d->service;
0153 }
0154 
0155 const KSocketAddress &KReverseResolver::address() const
0156 {
0157     return d->addr;
0158 }
0159 
0160 bool KReverseResolver::start()
0161 {
0162     if (d->worker != nullptr) {
0163         return true;    // already started
0164     }
0165 
0166     d->worker = new ReverseThread(d->addr, d->flags);
0167     d->worker->m_parent = this;
0168 
0169     RequestData *req = new RequestData;
0170     req->obj = nullptr;
0171     req->input = nullptr;
0172     req->requestor = nullptr;
0173     req->worker = d->worker;
0174     KResolverManager::manager()->dispatch(req);
0175     return true;
0176 }
0177 
0178 bool KReverseResolver::event(QEvent *e)
0179 {
0180     if (e->type() != KReverseResolverEvent::myType) {
0181         return QObject::event(e);    // call parent
0182     }
0183 
0184     KReverseResolverEvent *re = static_cast<KReverseResolverEvent *>(e);
0185     d->node = re->node;
0186     d->service = re->service;
0187     d->success = re->success;
0188 
0189     // don't delete d->worker!
0190     // KResolverManager::doNotifying takes care of that, if it hasn't already
0191     d->worker = nullptr;
0192 
0193     // emit signal
0194     emit finished(*this);
0195 
0196     return true;
0197 }
0198 
0199 bool KReverseResolver::resolve(const KSocketAddress &addr, QString &node,
0200                                QString &serv, int flags)
0201 {
0202     ReverseThread th(addr, flags);
0203     if (th.run()) {
0204         node = th.node;
0205         serv = th.service;
0206         return true;
0207     }
0208     return false;
0209 }
0210 
0211 bool KReverseResolver::resolve(const struct sockaddr *sa, quint16 salen,
0212                                QString &node, QString &serv, int flags)
0213 {
0214     return resolve(KSocketAddress(sa, salen), node, serv, flags);
0215 }
0216 
0217 bool ReverseThread::run()
0218 {
0219     int err;
0220     char h[NI_MAXHOST], s[NI_MAXSERV];
0221     int niflags = 0;
0222 
0223     h[0] = s[0] = '\0';
0224 
0225     if (m_flags & KReverseResolver::NumericHost) {
0226         niflags |= NI_NUMERICHOST;
0227     }
0228     if (m_flags & KReverseResolver::NumericService) {
0229         niflags |= NI_NUMERICSERV;
0230     }
0231     if (m_flags & KReverseResolver::NodeNameOnly) {
0232         niflags |= NI_NOFQDN;
0233     }
0234     if (m_flags & KReverseResolver::Datagram) {
0235         niflags |= NI_DGRAM;
0236     }
0237     if (m_flags & KReverseResolver::ResolutionRequired) {
0238         niflags |= NI_NAMEREQD;
0239     }
0240 
0241     {
0242 #ifdef NEED_MUTEX
0243         QMutexLocker locker(&::getXXbyYYmutex);
0244 #endif
0245         err = ::getnameinfo(m_addr, m_addr.length(),
0246                             h, sizeof(h) - 1, s, sizeof(s) - 1, niflags);
0247     }
0248 
0249     if (err == 0) {
0250         node = KResolver::domainToUnicode(QLatin1String(h));
0251         service = QLatin1String(s);
0252         success = true;
0253     } else {
0254         node.clear(); service.clear();
0255         success = false;
0256     }
0257 
0258     return success;
0259 }
0260 
0261 bool ReverseThread::postprocess()
0262 {
0263     // post an event
0264     if (m_parent)
0265         QCoreApplication::postEvent(m_parent,
0266                                     new KReverseResolverEvent(node, service, success));
0267     return true;
0268 }
0269 
0270 #include "moc_k3reverseresolver.cpp"