summaryrefslogtreecommitdiffstats
path: root/tdecore/network/kresolver_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'tdecore/network/kresolver_p.h')
-rw-r--r--tdecore/network/kresolver_p.h353
1 files changed, 353 insertions, 0 deletions
diff --git a/tdecore/network/kresolver_p.h b/tdecore/network/kresolver_p.h
new file mode 100644
index 000000000..7f74c6fe6
--- /dev/null
+++ b/tdecore/network/kresolver_p.h
@@ -0,0 +1,353 @@
+/* -*- C++ -*-
+ * Copyright (C) 2003-2005 Thiago Macieira <thiago.macieira@kdemail.net>
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef KRESOLVER_P_H
+#define KRESOLVER_P_H
+
+#include <config.h>
+#include <sys/types.h>
+
+#include <tqstring.h>
+#include <tqcstring.h>
+#include <tqvaluelist.h>
+#include <tqptrlist.h>
+#include <tqptrqueue.h>
+#include <tqthread.h>
+#include <tqmutex.h>
+#include <tqwaitcondition.h>
+#include <tqsemaphore.h>
+#include <tqevent.h>
+
+#include "kresolver.h"
+
+/* decide whether we need a mutex */
+#if !defined(HAVE_GETPROTOBYNAME_R) || !defined(HAVE_GETSERVBYNAME_R) || !defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETSERVBYPORT_R)
+# define NEED_MUTEX
+extern TQMutex getXXbyYYmutex;
+#endif
+
+/* some systems have the functions, but don't declare them */
+#if defined(HAVE_GETSERVBYNAME_R) && !HAVE_DECL_GETSERVBYNAME_R
+extern "C" {
+ struct servent;
+ extern int getservbyname_r(const char* serv, const char* proto,
+ struct servent* servbuf,
+ char* buf, size_t buflen,
+ struct servent** result);
+ extern int getservbyport_r(int port, const char* proto,
+ struct servent* servbuf,
+ char* buf, size_t buflen,
+ struct servent** result);
+
+ struct protoent;
+ extern int getprotobyname_r(const char* proto, struct protoent* protobuf,
+ char *buf, size_t buflen,
+ struct protoent** result);
+ extern int getprotobynumber_r(int proto, struct protoent* protobuf,
+ char *buf, size_t buflen,
+ struct protoent** result);
+}
+#endif
+
+/* decide whether res_init is thread-safe or not */
+#if defined(__GLIBC__)
+# undef RES_INIT_THREADSAFE
+#endif
+
+namespace KNetwork
+{
+ // defined in network/qresolverworkerbase.h
+ class KResolverWorkerBase;
+ class KResolverWorkerFactoryBase;
+ class KResolverPrivate;
+
+ namespace Internal
+ {
+ class KResolverManager;
+ class KResolverThread;
+ struct RequestData;
+
+ struct InputData
+ {
+ TQString node, service;
+ TQCString protocolName;
+ int flags;
+ int familyMask;
+ int socktype;
+ int protocol;
+ };
+ }
+
+ class KResolverPrivate
+ {
+ public:
+ // parent class. Should never be changed!
+ KResolver* parent;
+ bool deleteWhenDone : 1;
+ bool waiting : 1;
+
+ // class status. Should not be changed by worker threads!
+ volatile int status;
+ volatile int errorcode, syserror;
+
+ // input data. Should not be changed by worker threads!
+ Internal::InputData input;
+
+ // mutex
+ TQMutex mutex;
+
+ // output data
+ KResolverResults results;
+
+ KResolverPrivate(KResolver* _parent,
+ const TQString& _node = TQString::null,
+ const TQString& _service = TQString::null)
+ : parent(_parent), deleteWhenDone(false), waiting(false),
+ status(0), errorcode(0), syserror(0)
+ {
+ input.node = _node;
+ input.service = _service;
+ input.flags = 0;
+ input.familyMask = KResolver::AnyFamily;
+ input.socktype = 0;
+ input.protocol = 0;
+
+ results.setAddress(_node, _service);
+ }
+ };
+
+ namespace Internal
+ {
+ struct RequestData
+ {
+ // worker threads should not change values in the input data
+ KNetwork::KResolverPrivate *obj;
+ const KNetwork::Internal::InputData *input;
+ KNetwork::KResolverWorkerBase *worker; // worker class
+ RequestData *requestor; // class that requested us
+
+ volatile int nRequests; // how many requests that we made we still have left
+ };
+
+ /*
+ * @internal
+ * This class is the resolver manager
+ */
+ class KResolverManager
+ {
+ public:
+ enum EventTypes
+ { ResolutionCompleted = 1576 }; // arbitrary value;
+
+ /*
+ * This wait condition is used to notify wait states (KResolver::wait) that
+ * the resolver manager has finished processing one or more objects. All
+ * objects in wait state will be woken up and will check if they are done.
+ * If they aren't, they will go back to sleeping.
+ */
+ TQWaitCondition notifyWaiters;
+
+ private:
+ /*
+ * This variable is used to count the number of threads that are running
+ */
+ volatile unsigned short runningThreads;
+
+ /*
+ * This variable is used to count the number of threads that are currently
+ * waiting for data.
+ */
+ unsigned short availableThreads;
+
+ /*
+ * This wait condition is used to notify worker threads that there is new
+ * data available that has to be processed. All worker threads wait on this
+ * waitcond for a limited amount of time.
+ */
+ TQWaitCondition feedWorkers;
+
+ // this mutex protects the data in this object
+ TQMutex mutex;
+
+ // hold a list of all the current threads we have
+ TQPtrList<KResolverThread> workers;
+
+ // hold a list of all the new requests we have
+ TQPtrList<RequestData> newRequests;
+
+ // hold a list of all the requests in progress we have
+ TQPtrList<RequestData> currentRequests;
+
+ // hold a list of all the workers we have
+ TQPtrList<KNetwork::KResolverWorkerFactoryBase> workerFactories;
+
+ // private constructor
+ KResolverManager();
+
+ public:
+ static KResolverManager* manager() KDE_NO_EXPORT; // creates and returns the global manager
+
+ // destructor
+ ~KResolverManager();
+
+ /*
+ * Register this thread in the pool
+ */
+ void registerThread(KResolverThread* id);
+
+ /*
+ * Unregister this thread from the pool
+ */
+ void unregisterThread(KResolverThread* id);
+
+ /*
+ * Requests new data to work on.
+ *
+ * This function should only be called from a worker thread. This function
+ * is thread-safe.
+ *
+ * If there is data to be worked on, this function will return it. If there is
+ * none, this function will return a null pointer.
+ */
+ RequestData* requestData(KResolverThread* id, int maxWaitTime);
+
+ /*
+ * Releases the resources and returns the resolved data.
+ *
+ * This function should only be called from a worker thread. It is
+ * thread-safe. It does not post the event to the manager.
+ */
+ void releaseData(KResolverThread *id, RequestData* data);
+
+ /*
+ * Registers a new worker class by way of its factory.
+ *
+ * This function is NOT thread-safe.
+ */
+ void registerNewWorker(KNetwork::KResolverWorkerFactoryBase *factory);
+
+ /*
+ * Enqueues new resolutions.
+ */
+ void enqueue(KNetwork::KResolver *obj, RequestData* requestor);
+
+ /*
+ * Dispatch a new request
+ */
+ void dispatch(RequestData* data);
+
+ /*
+ * Dequeues a resolution.
+ */
+ void dequeue(KNetwork::KResolver *obj);
+
+ /*
+ * Notifies the manager that the given resolution is about to
+ * be deleted. This function should only be called by the
+ * KResolver destructor.
+ */
+ void aboutToBeDeleted(KNetwork::KResolver *obj);
+
+ /*
+ * Notifies the manager that new events are ready.
+ */
+ void newEvent();
+
+ /*
+ * This function is called by the manager to receive a new event. It operates
+ * on the @ref eventSemaphore semaphore, which means it will block till there
+ * is at least one event to go.
+ */
+ void receiveEvent();
+
+ private:
+ /*
+ * finds a suitable worker for this request
+ */
+ KNetwork::KResolverWorkerBase *findWorker(KNetwork::KResolverPrivate *p);
+
+ /*
+ * finds data for this request
+ */
+ RequestData* findData(KResolverThread*);
+
+ /*
+ * Handle completed requests.
+ *
+ * This function is called by releaseData above
+ */
+ void handleFinished();
+
+ /*
+ * Handle one completed request.
+ *
+ * This function is called by handleFinished above.
+ */
+ bool handleFinishedItem(RequestData* item);
+
+ /*
+ * Notifies the parent class that this request is done.
+ *
+ * This function deletes the request
+ */
+ void doNotifying(RequestData *p);
+
+ /*
+ * Dequeues and notifies an object that is in Queued state
+ * Returns true if the object is no longer queued; false if it could not
+ * be dequeued (i.e., it's running)
+ */
+ bool dequeueNew(KNetwork::KResolver* obj);
+ };
+
+ /*
+ * @internal
+ * This class is a worker thread in the resolver system.
+ * This class must be thread-safe.
+ */
+ class KResolverThread: public TQThread
+ {
+ private:
+ // private constructor. Only the manager can create worker threads
+ KResolverThread();
+ RequestData* data;
+
+ protected:
+ virtual void run(); // here the thread starts
+
+ friend class KNetwork::Internal::KResolverManager;
+ friend class KNetwork::KResolverWorkerBase;
+
+ public:
+ bool checkResolver(); // see KResolverWorkerBase::checkResolver
+ void acquireResolver(); // see KResolverWorkerBase::acquireResolver
+ void releaseResolver(); // see KResolverWorkerBase::releaseResolver
+ };
+
+ } // namespace Internal
+
+} // namespace KNetwork
+
+
+#endif