File indexing completed on 2025-04-27 13:05:23
0001 /* -*- C++ -*- 0002 * Copyright (C) 2003-2005 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 #ifndef KRESOLVER_P_H 0026 #define KRESOLVER_P_H 0027 0028 #include <config-network.h> 0029 #include <sys/types.h> 0030 0031 #include <QByteArray> 0032 #include <QList> 0033 #include <QThread> 0034 #include <QMutex> 0035 #include <QWaitCondition> 0036 #include <QSemaphore> 0037 #include <QEvent> 0038 0039 #include "k3resolver.h" 0040 0041 /* decide whether we need a mutex */ 0042 #if !HAVE_GETPROTOBYNAME_R || !HAVE_GETSERVBYNAME_R || !HAVE_GETHOSTBYNAME_R || !HAVE_GETSERVBYPORT_R 0043 # define NEED_MUTEX 0044 extern QMutex getXXbyYYmutex; 0045 #endif 0046 0047 /* some systems have the functions, but don't declare them */ 0048 #if HAVE_GETSERVBYNAME_R && !HAVE_GETSERVBYNAME_R_PROTO 0049 extern "C" { 0050 struct servent; 0051 extern int getservbyname_r(const char *serv, const char *proto, 0052 struct servent *servbuf, 0053 char *buf, size_t buflen, 0054 struct servent **result); 0055 extern int getservbyport_r(int port, const char *proto, 0056 struct servent *servbuf, 0057 char *buf, size_t buflen, 0058 struct servent **result); 0059 0060 struct protoent; 0061 extern int getprotobyname_r(const char *proto, struct protoent *protobuf, 0062 char *buf, size_t buflen, 0063 struct protoent **result); 0064 extern int getprotobynumber_r(int proto, struct protoent *protobuf, 0065 char *buf, size_t buflen, 0066 struct protoent **result); 0067 } 0068 #endif 0069 0070 /* decide whether res_init is thread-safe or not */ 0071 #if defined(__GLIBC__) 0072 # undef RES_INIT_THREADSAFE 0073 #endif 0074 0075 namespace KNetwork 0076 { 0077 // defined in network/qresolverworkerbase.h 0078 class KResolverWorkerBase; 0079 class KResolverWorkerFactoryBase; 0080 class KResolverPrivate; 0081 0082 namespace Internal 0083 { 0084 class KResolverManager; 0085 class KResolverThread; 0086 struct RequestData; 0087 0088 struct InputData { 0089 QString node, service; 0090 QByteArray protocolName; 0091 int flags; 0092 int familyMask; 0093 int socktype; 0094 int protocol; 0095 }; 0096 } 0097 0098 class KResolverPrivate 0099 { 0100 public: 0101 // parent class. Should never be changed! 0102 KResolver *parent; 0103 bool deleteWhenDone : 1; 0104 bool waiting : 1; 0105 0106 // class status. Should not be changed by worker threads! 0107 volatile int status; 0108 volatile int errorcode, syserror; 0109 0110 // input data. Should not be changed by worker threads! 0111 Internal::InputData input; 0112 0113 // mutex 0114 QMutex mutex; 0115 0116 // output data 0117 KResolverResults results; 0118 0119 KDELIBS4SUPPORT_DEPRECATED explicit KResolverPrivate(KResolver *_parent, 0120 const QString &_node = QString(), 0121 const QString &_service = QString()) 0122 : parent(_parent), deleteWhenDone(false), waiting(false), 0123 status(0), errorcode(0), syserror(0) 0124 { 0125 input.node = _node; 0126 input.service = _service; 0127 input.flags = 0; 0128 input.familyMask = KResolver::AnyFamily; 0129 input.socktype = 0; 0130 input.protocol = 0; 0131 0132 results.setAddress(_node, _service); 0133 } 0134 }; 0135 0136 namespace Internal 0137 { 0138 struct RequestData { 0139 // worker threads should not change values in the input data 0140 KNetwork::KResolverPrivate *obj; 0141 const KNetwork::Internal::InputData *input; 0142 KNetwork::KResolverWorkerBase *worker; // worker class 0143 RequestData *requestor; // class that requested us 0144 0145 volatile int nRequests; // how many requests that we made we still have left 0146 }; 0147 0148 /* 0149 * @internal 0150 * This class is the resolver manager 0151 */ 0152 class KResolverManager 0153 { 0154 public: 0155 enum EventTypes 0156 { ResolutionCompleted = 1576 }; // arbitrary value; 0157 0158 /* 0159 * This wait condition is used to notify wait states (KResolver::wait) that 0160 * the resolver manager has finished processing one or more objects. All 0161 * objects in wait state will be woken up and will check if they are done. 0162 * If they aren't, they will go back to sleeping. 0163 */ 0164 QWaitCondition notifyWaiters; 0165 0166 private: 0167 /* 0168 * This variable is used to count the number of threads that are running 0169 */ 0170 volatile unsigned short runningThreads; 0171 0172 /* 0173 * This variable is used to count the number of threads that are currently 0174 * waiting for data. 0175 */ 0176 unsigned short availableThreads; 0177 0178 /* 0179 * This wait condition is used to notify worker threads that there is new 0180 * data available that has to be processed. All worker threads wait on this 0181 * waitcond for a limited amount of time. 0182 */ 0183 QWaitCondition feedWorkers; 0184 0185 // this mutex protects the data in this object 0186 QMutex mutex; 0187 0188 // hold a list of all the current threads we have 0189 QList<KResolverThread *> workers; 0190 0191 // hold a list of all the new requests we have 0192 QList<RequestData *> newRequests; 0193 0194 // hold a list of all the requests in progress we have 0195 QList<RequestData *> currentRequests; 0196 0197 // hold a list of all the workers we have 0198 QList<KNetwork::KResolverWorkerFactoryBase *> workerFactories; 0199 0200 // private constructor 0201 KResolverManager(); 0202 0203 public: 0204 static KResolverManager *manager(); // creates and returns the global manager 0205 0206 // destructor 0207 ~KResolverManager(); 0208 0209 /* 0210 * Register this thread in the pool 0211 */ 0212 void registerThread(KResolverThread *id); 0213 0214 /* 0215 * Unregister this thread from the pool 0216 */ 0217 void unregisterThread(KResolverThread *id); 0218 0219 /* 0220 * Requests new data to work on. 0221 * 0222 * This function should only be called from a worker thread. This function 0223 * is thread-safe. 0224 * 0225 * If there is data to be worked on, this function will return it. If there is 0226 * none, this function will return a null pointer. 0227 */ 0228 RequestData *requestData(KResolverThread *id, int maxWaitTime); 0229 0230 /* 0231 * Releases the resources and returns the resolved data. 0232 * 0233 * This function should only be called from a worker thread. It is 0234 * thread-safe. It does not post the event to the manager. 0235 */ 0236 void releaseData(KResolverThread *id, RequestData *data); 0237 0238 /* 0239 * Registers a new worker class by way of its factory. 0240 * 0241 * This function is NOT thread-safe. 0242 */ 0243 void registerNewWorker(KNetwork::KResolverWorkerFactoryBase *factory); 0244 0245 /* 0246 * Enqueues new resolutions. 0247 */ 0248 void enqueue(KNetwork::KResolver *obj, RequestData *requestor); 0249 0250 /* 0251 * Dispatch a new request 0252 */ 0253 void dispatch(RequestData *data); 0254 0255 /* 0256 * Dequeues a resolution. 0257 */ 0258 void dequeue(KNetwork::KResolver *obj); 0259 0260 /* 0261 * Notifies the manager that the given resolution is about to 0262 * be deleted. This function should only be called by the 0263 * KResolver destructor. 0264 */ 0265 void aboutToBeDeleted(KNetwork::KResolver *obj); 0266 0267 /* 0268 * Notifies the manager that new events are ready. 0269 */ 0270 void newEvent(); 0271 0272 /* 0273 * This function is called by the manager to receive a new event. It operates 0274 * on the eventSemaphore() semaphore, which means it will block till there 0275 * is at least one event to go. 0276 */ 0277 void receiveEvent(); 0278 0279 private: 0280 /* 0281 * finds a suitable worker for this request 0282 */ 0283 KNetwork::KResolverWorkerBase *findWorker(KNetwork::KResolverPrivate *p); 0284 0285 /* 0286 * finds data for this request 0287 */ 0288 RequestData *findData(KResolverThread *); 0289 0290 /* 0291 * Handle completed requests. 0292 * 0293 * This function is called by releaseData above 0294 */ 0295 void handleFinished(); 0296 0297 /* 0298 * Handle one completed request. 0299 * 0300 * This function is called by handleFinished above. 0301 */ 0302 bool handleFinishedItem(RequestData *item); 0303 0304 /* 0305 * Notifies the parent class that this request is done. 0306 * 0307 * This function deletes the request 0308 */ 0309 void doNotifying(RequestData *p); 0310 0311 /* 0312 * Dequeues and notifies an object that is in Queued state 0313 * Returns true if the object is no longer queued; false if it could not 0314 * be dequeued (i.e., it's running) 0315 */ 0316 bool dequeueNew(KNetwork::KResolver *obj); 0317 }; 0318 0319 /* 0320 * @internal 0321 * This class is a worker thread in the resolver system. 0322 * This class must be thread-safe. 0323 */ 0324 class KResolverThread: public QThread 0325 { 0326 private: 0327 // private constructor. Only the manager can create worker threads 0328 KResolverThread(); 0329 RequestData *data; 0330 0331 protected: 0332 void run() override; // here the thread starts 0333 0334 friend class KNetwork::Internal::KResolverManager; 0335 friend class KNetwork::KResolverWorkerBase; 0336 0337 public: 0338 bool checkResolver(); // see KResolverWorkerBase::checkResolver 0339 void acquireResolver(); // see KResolverWorkerBase::acquireResolver 0340 void releaseResolver(); // see KResolverWorkerBase::releaseResolver 0341 }; 0342 0343 } // namespace Internal 0344 0345 } // namespace KNetwork 0346 0347 #endif