summaryrefslogtreecommitdiffstats
path: root/kdecore/network/kresolverworkerbase.h
blob: 8776e9142610c5f46ee800f70b8303a54668f040 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
/*  -*- C++ -*-
 *  Copyright (C) 2003,2004 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 KRESOLVERWORKERBASE_H
#define KRESOLVERWORKERBASE_H

#include "kresolver.h"

// forward declarations
class QString;
template <class T> class QValueList;

namespace KNetwork {

  namespace Internal
  {
    class KResolverThread;
    struct InputData;
  }

/** @internal
 * This class is the base functionality for a resolver worker. That is,
 * the class that does the actual work.
 *
 * In the future, this class might be exposed to allow plug-ins. So, try and 
 * make it binary compatible.
 *
 * Note that hostnames are still encoded in Unicode at this point. It's up to
 * the worker class to decide which encoding to use. In the case of DNS, 
 * an ASCII Compatible Encoding (ACE) must be used. 
 * See @ref KResolver::domainToAscii. 
 *
 * Also specially note that the run method in this class is called in a
 * thread that is not the program's main thread. So do not do anything there
 * that you shouldn't!
 *
 * @class KResolverWorkerBase kresolverworkerbase.h kresolverworkerbase.h
 */
class KResolverWorkerBase
{
public:

  /**
   * Helper class for locking the resolver subsystem. 
   * Similar to QMutexLocker.
   * 
   * @author Luís Pedro Coelho
   * @since 3.4
   */
  class ResolverLocker
  {
  public:
    /** 
     * Constructor. Acquires a lock.
     */
    ResolverLocker(KResolverWorkerBase* parent)
      : parent( parent ) 
    {
      parent->acquireResolver();
    }

    /** 
     * Destructor. Releases the lock.
     */
    ~ResolverLocker() 
    {
      parent->releaseResolver();
    }

    /**
     * Releases the lock and then reacquires it.
     * It may be necessary to call this if the resolving function
     * decides to retry.
     */
    void openClose() 
    {
      parent->releaseResolver();
      parent->acquireResolver();
    }

  private:
    /// @internal
    KResolverWorkerBase* parent;
  };
private:
  // this will be like our d pointer
  KNetwork::Internal::KResolverThread *th;
  const KNetwork::Internal::InputData *input;
  friend class KNetwork::Internal::KResolverThread;
  friend class KNetwork::Internal::KResolverManager;
  friend class KResolverWorkerBase::ResolverLocker;

  int m_finished : 1;
  int m_reserved : 31;		// reserved

public:
  /**
   * Derived classes will put their resolved data in this list, or will
   * leave it empty in case of error.
   *
   * Status and error codes should also be stored in this object (the
   * @ref setError function does that).
   */
  KResolverResults results;

public:
  // default constructor
  KResolverWorkerBase();

  // virtual destructor
  virtual ~KResolverWorkerBase();

  /**
   * This is the hostname to be looked for
   */
  QString nodeName() const;

  /**
   * And this is the service name
   */
  QString serviceName() const;

  /**
   * gets the flags
   */
  int flags() const;

  /**
   * gets the family mask
   */
  int familyMask() const;

  /**
   * gets the socket type
   */
  int socketType() const;

  /**
   * gets the protocol number
   */
  int protocol() const;

  /**
   * gets the protocol name, if applicable
   */
  QCString protocolName() const;

  /**
   * Call this function to indicate that processing
   * has finished. This is useful in the preprocessing
   * stage, to indicate that @ref run doesn't have to be
   * called.
   */
  void finished();

protected:
  // like a QThread
  /**
   * This is the function that should be overriden in derived classes.
   * 
   * Derived classes will do their blocking job in this function and return
   * either success or failure to work (not the lookup). That is, whether the
   * lookup result was a domain found or not, if we got our answer, we should
   * indicate success. The error itself must be set with @ref setError.
   *
   * \b Important: this function gets called in a separate thread!
   * 
   * @return true on success
   */
  virtual bool run() = 0;

  /**
   * This function gets called during pre processing for this class and you must
   * override it.
   *
   * \b Important: this function gets called in the main event thread. And it MUST
   * NOT block.
   *
   * This function can be used for an object to determine if it will be able
   * to resolve the given data or not even before launching into a blocking
   * operation. This function should return true if the object is capable of
   * handling this kind of data; false otherwise. Note that the return value
   * of 'true' means that the object's blocking answer will be considered authoritative.
   *
   * This function MUST NOT queue further requests. Leave that to @ref run.
   *
   * This function is pure virtual; you must override it.
   *
   * @return true on success
   */
  virtual bool preprocess() = 0;

  /**
   * This function gets called during post processing for this class.
   *
   * \b Important: this function gets called in the main event thread. And it MUST
   * NOT block.
   *
   * @returns true on success
   */
  virtual bool postprocess();

  /**
   * Sets the error
   */
  inline void setError(int errorcode, int syserror = 0)
  { results.setError(errorcode, syserror); }

  /**
   * Enqueue the given resolver for post-processing.
   *
   * Use this function to make the manager call for another resolution.
   * This is suitable for workers that do post-processing.
   *
   * The manager will make sure that any requests enqueued by this function
   * are done before calling the postprocessing function, which you should 
   * override.
   *
   * \b Important: do use KResolver's own enqueueing functions (i.e., @ref KResolver::start). 
   * Instead, use this function.
   *
   * @returns true on successful queueing or false if a problem ocurred
   */
  bool enqueue(KResolver* other);

  /**
   * @overload
   */
  bool enqueue(KResolverWorkerBase* worker);

  /**
   * Checks the resolver subsystem status.
   * @returns true if the resolver subsystem changed, false otherwise.
   *          If this function returns true, it might be necessary to
   *          restart the resolution altogether.
   * @since 3.4
   */
  bool checkResolver();

  /**
   * This function has to be called from the resolver workers that require
   * use of the DNS resolver code (i.e., res_* functions, generally in
   * libresolv). It indicates that the function is starting a resolution
   * and that the resolver backend shouldn't change asynchronously.
   *
   * If any pending res_init's are required, they will be performed before 
   * this function returns.
   *
   * @since 3.4
   */
  void acquireResolver();

  /**
   * This function is the counterpart for @ref acquireResolver: the worker
   * thread indicates that it's done with the resolver.
   *
   * @since 3.4
   */
  void releaseResolver();

};

/** @internal
 * This class provides functionality for creating and registering worker classes.
 *
 * @class KResolverWorkerFactoryBase kresolverworkerbase.h kresolverworkerbase.h
 */
class KResolverWorkerFactoryBase
{
public:
  virtual KResolverWorkerBase* create() const = 0;

  /**
   * Wrapper call to register workers
   *
   * It is NOT thread-safe!
   */
  static void registerNewWorker(KResolverWorkerFactoryBase* factory);
};

/** @internal
 * This class provides functionality for creating and registering worker classes.
 *
 * @class KResolverWorkerFactory kresolverworkerbase.h kresolverworkerbase.h
 */
template<class Worker>
class KResolverWorkerFactory: public KResolverWorkerFactoryBase
{
public:
  virtual KResolverWorkerBase* create() const
  { return new Worker; }
};

}				// namespace KNetwork

#endif