kreverseresolver.cpp
00001 /* -*- C++ -*- 00002 * Copyright (C) 2003 Thiago Macieira <thiago.macieira@kdemail.net> 00003 * 00004 * 00005 * Permission is hereby granted, free of charge, to any person obtaining 00006 * a copy of this software and associated documentation files (the 00007 * "Software"), to deal in the Software without restriction, including 00008 * without limitation the rights to use, copy, modify, merge, publish, 00009 * distribute, sublicense, and/or sell copies of the Software, and to 00010 * permit persons to whom the Software is furnished to do so, subject to 00011 * the following conditions: 00012 * 00013 * The above copyright notice and this permission notice shall be included 00014 * in all copies or substantial portions of the Software. 00015 * 00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 00020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 00021 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 00022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 #include "config.h" 00026 00027 // System includes 00028 #include <sys/types.h> 00029 #include <sys/socket.h> 00030 #include <netdb.h> 00031 #include <signal.h> 00032 00033 // Qt 00034 #include <tqevent.h> 00035 #include <tqmutex.h> 00036 #include <tqapplication.h> 00037 00038 // Us 00039 #include "kreverseresolver.h" 00040 #include "kresolver_p.h" 00041 #include "kresolverworkerbase.h" 00042 #include "ksocketaddress.h" 00043 00044 #ifndef HAVE_GETNAMEINFO 00045 // FIXME KDE4: 00046 // move to syssocket or adapt 00047 # include "netsupp.h" 00048 #endif 00049 00050 using namespace KNetwork; 00051 using namespace KNetwork::Internal; 00052 00053 namespace 00054 { 00055 class ReverseThread: public KResolverWorkerBase 00056 { 00057 public: 00058 ReverseThread(const KSocketAddress& addr, int flags) 00059 : m_addr(addr), m_flags(flags), m_parent(0L) 00060 { } 00061 00062 virtual ~ReverseThread() 00063 { } 00064 00065 virtual bool preprocess() 00066 { return true; } 00067 virtual bool run(); 00068 virtual bool postprocess(); 00069 00070 // input: 00071 KSocketAddress m_addr; 00072 int m_flags; 00073 KReverseResolver *m_parent; 00074 00075 // output: 00076 TQString node; 00077 TQString service; 00078 bool success; 00079 }; 00080 00081 class KReverseResolverEvent: public TQEvent 00082 { 00083 public: 00084 static const int myType = TQEvent::User + 63; // arbitrary value 00085 TQString node; 00086 TQString service; 00087 bool success; 00088 00089 KReverseResolverEvent(const TQString& _node, const TQString& _service, 00090 bool _success) 00091 : TQEvent((Type)myType), node(_node), 00092 service(_service), success(_success) 00093 { } 00094 }; 00095 } 00096 00097 class KNetwork::KReverseResolverPrivate 00098 { 00099 public: 00100 TQString node; 00101 TQString service; 00102 KSocketAddress addr; 00103 int flags; 00104 00105 ReverseThread* worker; 00106 bool success; 00107 00108 inline KReverseResolverPrivate(const KSocketAddress& _addr) 00109 : addr(_addr), worker(0L), success(false) 00110 { } 00111 }; 00112 00113 KReverseResolver::KReverseResolver(const KSocketAddress& addr, int flags, 00114 TQObject *parent, const char* name) 00115 : TQObject(parent, name), d(new KReverseResolverPrivate(addr)) 00116 { 00117 d->flags = flags; 00118 } 00119 00120 KReverseResolver::~KReverseResolver() 00121 { 00122 if (d->worker) 00123 d->worker->m_parent = 0L; 00124 } 00125 00126 bool KReverseResolver::isRunning() const 00127 { 00128 return d->worker != 0L; 00129 } 00130 00131 bool KReverseResolver::success() const 00132 { 00133 return !isRunning() && d->success; 00134 } 00135 00136 bool KReverseResolver::failure() const 00137 { 00138 return !isRunning() && !d->success; 00139 } 00140 00141 TQString KReverseResolver::node() const 00142 { 00143 return d->node; 00144 } 00145 00146 TQString KReverseResolver::service() const 00147 { 00148 return d->service; 00149 } 00150 00151 const KSocketAddress& KReverseResolver::address() const 00152 { 00153 return d->addr; 00154 } 00155 00156 bool KReverseResolver::start() 00157 { 00158 if (d->worker != 0L) 00159 return true; // already started 00160 00161 d->worker = new ReverseThread(d->addr, d->flags); 00162 d->worker->m_parent = this; 00163 00164 RequestData *req = new RequestData; 00165 req->obj = 0L; 00166 req->input = 0L; 00167 req->requestor = 0L; 00168 req->worker = d->worker; 00169 KResolverManager::manager()->dispatch(req); 00170 return true; 00171 } 00172 00173 bool KReverseResolver::event(TQEvent *e) 00174 { 00175 if (e->type() != KReverseResolverEvent::myType) 00176 return TQObject::event(e); // call parent 00177 00178 KReverseResolverEvent *re = static_cast<KReverseResolverEvent*>(e); 00179 d->node = re->node; 00180 d->service = re->service; 00181 d->success = re->success; 00182 00183 // don't delete d->worker! 00184 // KResolverManager::doNotifying takes care of that, if it hasn't already 00185 d->worker = 0L; 00186 00187 // emit signal 00188 emit finished(*this); 00189 00190 return true; 00191 } 00192 00193 bool KReverseResolver::resolve(const KSocketAddress& addr, TQString& node, 00194 TQString& serv, int flags) 00195 { 00196 ReverseThread th(addr, flags); 00197 if (th.run()) 00198 { 00199 node = th.node; 00200 serv = th.service; 00201 return true; 00202 } 00203 return false; 00204 } 00205 00206 bool KReverseResolver::resolve(const struct sockaddr* sa, TQ_UINT16 salen, 00207 TQString& node, TQString& serv, int flags) 00208 { 00209 return resolve(KSocketAddress(sa, salen), node, serv, flags); 00210 } 00211 00212 bool ReverseThread::run() 00213 { 00214 int err; 00215 char h[NI_MAXHOST], s[NI_MAXSERV]; 00216 int niflags = 0; 00217 00218 h[0] = s[0] = '\0'; 00219 00220 if (m_flags & KReverseResolver::NumericHost) 00221 niflags |= NI_NUMERICHOST; 00222 if (m_flags & KReverseResolver::NumericService) 00223 niflags |= NI_NUMERICSERV; 00224 if (m_flags & KReverseResolver::NodeNameOnly) 00225 niflags |= NI_NOFQDN; 00226 if (m_flags & KReverseResolver::Datagram) 00227 niflags |= NI_DGRAM; 00228 if (m_flags & KReverseResolver::ResolutionRequired) 00229 niflags |= NI_NAMEREQD; 00230 00231 { 00232 #ifdef NEED_MUTEX 00233 TQMutexLocker locker(&::getXXbyYYmutex); 00234 #endif 00235 err = ::getnameinfo(m_addr, m_addr.length(), 00236 h, sizeof(h) - 1, s, sizeof(s) - 1, niflags); 00237 } 00238 00239 if (err == 0) 00240 { 00241 node = KResolver::domainToUnicode(TQString::fromLatin1(h)); 00242 service = TQString::fromLatin1(s); 00243 success = true; 00244 } 00245 else 00246 { 00247 node = service = TQString::null; 00248 success = false; 00249 } 00250 00251 return success; 00252 } 00253 00254 bool ReverseThread::postprocess() 00255 { 00256 // post an event 00257 if (m_parent) 00258 TQApplication::postEvent(m_parent, 00259 new KReverseResolverEvent(node, service, success)); 00260 return true; 00261 } 00262 00263 #include "kreverseresolver.moc"