~ubuntu-branches/ubuntu/quantal/psi/quantal

« back to all changes in this revision

Viewing changes to iris/irisnet/netnames.h

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2009-09-25 17:49:51 UTC
  • mfrom: (6.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090925174951-lvm7kdap82o8xhn3
Tags: 0.13-1
* Updated to upstream version 0.13
* Set Standards-Version to 3.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2006  Justin Karneges
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Lesser General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2.1 of the License, or (at your option) any later version.
8
 
 *
9
 
 * This library is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
 * Lesser General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Lesser General Public
15
 
 * License along with this library; if not, write to the Free Software
16
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
 
 * 02110-1301  USA
18
 
 *
19
 
 */
20
 
 
21
 
#ifndef NETNAMES_H
22
 
#define NETNAMES_H
23
 
 
24
 
#include <QtCore>
25
 
#include <QtNetwork>
26
 
#include "irisnetglobal.h"
27
 
 
28
 
namespace XMPP {
29
 
 
30
 
class NameManager;
31
 
 
32
 
class IRISNET_EXPORT NetNames
33
 
{
34
 
public:
35
 
        // free any shared data, shutdown internal dns sessions if necessary.
36
 
        static void cleanup();
37
 
 
38
 
        // return current diagnostic text, clear the buffer.
39
 
        static QString diagnosticText();
40
 
 
41
 
        // convert idn names
42
 
        static QByteArray idnaFromString(const QString &in);
43
 
        static QString idnaToString(const QByteArray &in);
44
 
 
45
 
        // dns escaping
46
 
        static QByteArray escapeDomain(const QByteArray &in);
47
 
        static QByteArray unescapeDomain(const QByteArray &in);
48
 
 
49
 
private:
50
 
        NetNames();
51
 
};
52
 
 
53
 
/**
54
 
   \brief Provides a DNS record
55
 
 
56
 
   NameRecord provides a DNS (Domain Name System) record, which is information assicated with a domain name.  For most purposes, the information is an IP address.  However, DNS records are capable of holding a variety of data types, such as named pointers to other domain names and even arbitrary text strings.  The results of a NameResolver operation are a list of NameRecords.
57
 
 
58
 
   The most common type is the address record, "A", which contains an IPv4 address.  Here is an example of how to get the IP address out of an address record:
59
 
 
60
 
\code
61
 
NameRecord record = ... // obtain a record from somewhere
62
 
if(record.type() == NameRecord::A)
63
 
{
64
 
        QHostAddress ip = record.address(); // get the IP
65
 
        ...
66
 
}
67
 
\endcode
68
 
 
69
 
   Getting the data out of a NameRecord involves calling the right retrieval functions, depending on the type.  Many types share retrieval functions.  For example, the "AAAA" type holds an IPv6 address, which is accessed the same way as the "A" type, by calling address().  See the NameRecord::Type enum for further information about which retrieval functions should be called for each type.
70
 
 
71
 
   To create a NameRecord, use setOwner() and setTTL() as necessary, and then call one of the set<em>X</em> functions (where <em>X</em> is the desired type).  For example, to set an A or AAAA record, use setAddress() like this:
72
 
 
73
 
\code
74
 
// make example.com the owner, with 1 hour TTL
75
 
NameRecord record("example.com", 3600);
76
 
record.setAddress(QHostAddress("1.2.3.4"));
77
 
\endcode
78
 
 
79
 
   Note that in the case of setAddress(), the record type need not be specified.  NameRecord will determine the type to use based on the given QHostAddress.
80
 
 
81
 
   \sa NameResolver
82
 
*/
83
 
class IRISNET_EXPORT NameRecord
84
 
{
85
 
public:
86
 
        /**
87
 
                \brief The type of DNS record
88
 
 
89
 
                The retrieval functions are shown for each type.
90
 
        */
91
 
        enum Type
92
 
        {
93
 
                A,     ///< IPv4 address.  Use address().
94
 
                Aaaa,  ///< IPv6 address.  Use address().
95
 
                Mx,    ///< Mail server.  Use name() and priority().
96
 
                Srv,   ///< Generic server.  Use name(), port(), priority(), and weight().
97
 
                Cname, ///< Canonical name.  Use name().
98
 
                Ptr,   ///< Pointer.  Use name().
99
 
                Txt,   ///< List of text strings.  Use texts().
100
 
                Hinfo, ///< Host information.  Use cpu() and os().
101
 
                Ns,    ///< Name server.  Use name().
102
 
                Null,  ///< Null type.  Use rawData().
103
 
                Any    ///< "Any record", for use with NameResolver::start() only.  A NameRecord object will never be of this type.
104
 
        };
105
 
 
106
 
        /**
107
 
           \brief Constructs a null record object
108
 
 
109
 
           \sa isNull
110
 
        */
111
 
        NameRecord();
112
 
 
113
 
        /**
114
 
           \brief Constructs a partially initialized record object, with the given \a owner and \a ttl
115
 
 
116
 
           For the record to be usable, call an appropriate set<em>X</em> function (where <em>X</em> is the desired type) afterwards.
117
 
        */
118
 
        NameRecord(const QByteArray &owner, int ttl);
119
 
 
120
 
        /**
121
 
           \brief Constructs a copy of \a from
122
 
        */
123
 
        NameRecord(const NameRecord &from);
124
 
 
125
 
        /**
126
 
           \brief Destroys the record object
127
 
        */
128
 
        ~NameRecord();
129
 
 
130
 
        /**
131
 
           \brief Assigns \a from to this object and returns a reference to this object
132
 
        */
133
 
        NameRecord & operator=(const NameRecord &from);
134
 
 
135
 
        /**
136
 
           \brief Returns true if this record object is null, otherwise returns false
137
 
 
138
 
           Be sure not to confuse a null object with the NULL type (NameRecord::Null).  Don't ask why DNS has a type called NULL that contains valid data.
139
 
        */
140
 
        bool isNull() const; // don't confuse with Null type
141
 
 
142
 
        /**
143
 
           \brief Returns the owner of this record
144
 
 
145
 
           The owner is usually not a useful attribute, since it will be the same as the name searched for with NameResolver.  For example, if the A record of "example.com" is looked up, then the resulting records will all have "example.com" as the owner.
146
 
 
147
 
           \sa setOwner
148
 
        */
149
 
        QByteArray owner() const;
150
 
 
151
 
        /**
152
 
           \brief Returns the TTL (time-to-live) of this record
153
 
 
154
 
           This is the number of seconds the record should be considered valid, which is useful information when performing caching.
155
 
 
156
 
           As a special exception, a TTL of 0 when performing a long-lived lookup indicates that a record is no longer available.
157
 
 
158
 
           \sa setTTL
159
 
        */
160
 
        int ttl() const;
161
 
 
162
 
        /**
163
 
           \brief Returns the type of this record
164
 
        */
165
 
        Type type() const;
166
 
 
167
 
        /**
168
 
           \brief Returns the IP address
169
 
 
170
 
           For NameRecord::A and NameRecord::Aaaa types.
171
 
        */
172
 
        QHostAddress address() const;
173
 
 
174
 
        /**
175
 
           \brief Returns the domain name
176
 
 
177
 
           For NameRecord::Mx, NameRecord::Srv, NameRecord::Cname, NameRecord::Ptr, and NameRecord::Ns types.
178
 
        */
179
 
        QByteArray name() const;
180
 
 
181
 
        /**
182
 
           \brief Returns the priority
183
 
 
184
 
           For NameRecord::Mx and NameRecord::Srv types.
185
 
        */
186
 
        int priority() const;
187
 
 
188
 
        /**
189
 
           \brief Returns the weight
190
 
 
191
 
           For the NameRecord::Srv type.
192
 
        */
193
 
        int weight() const;
194
 
 
195
 
        /**
196
 
           \brief Returns the port
197
 
 
198
 
           For the NameRecord::Srv type.
199
 
        */
200
 
        int port() const;
201
 
 
202
 
        /**
203
 
           \brief Returns the list of text strings
204
 
 
205
 
           For the NameRecord::Txt type.
206
 
        */
207
 
        QList<QByteArray> texts() const;
208
 
 
209
 
        /**
210
 
           \brief Returns the architecture identifier string
211
 
 
212
 
           For the NameRecord::Hinfo type.
213
 
        */
214
 
        QByteArray cpu() const;
215
 
 
216
 
        /**
217
 
           \brief Returns the operating system identifier string
218
 
 
219
 
           For the NameRecord::Hinfo type.
220
 
        */
221
 
        QByteArray os() const;
222
 
 
223
 
        /**
224
 
           \brief Returns the raw data
225
 
 
226
 
           For the NameRecord::Null type.
227
 
        */
228
 
        QByteArray rawData() const;
229
 
 
230
 
        /**
231
 
           \brief Sets the owner of this record to \a name
232
 
 
233
 
           \sa owner
234
 
        */
235
 
        void setOwner(const QByteArray &name);
236
 
 
237
 
        /**
238
 
           \brief Sets the TTL (time-to-live) of this record to \a ttl seconds
239
 
 
240
 
           \sa ttl
241
 
        */
242
 
        void setTTL(int seconds);
243
 
 
244
 
        /**
245
 
           \brief Set as A or AAAA record, with data \a a
246
 
 
247
 
           The protocol of \a a determines whether the type will be NameRecord::A or NameRecord::Aaaa.
248
 
        */
249
 
        void setAddress(const QHostAddress &a);
250
 
 
251
 
        /**
252
 
           \brief Set as MX record, with data \a name and \a priority
253
 
        */
254
 
        void setMx(const QByteArray &name, int priority);
255
 
 
256
 
        /**
257
 
           \brief Set as SRV record, with data \a name, \a port, \a priority, and \a weight
258
 
        */
259
 
        void setSrv(const QByteArray &name, int port, int priority, int weight);
260
 
 
261
 
        /**
262
 
           \brief Set as CNAME record, with data \a name
263
 
        */
264
 
        void setCname(const QByteArray &name);
265
 
 
266
 
        /**
267
 
           \brief Set as PTR record, with data \a name
268
 
        */
269
 
        void setPtr(const QByteArray &name);
270
 
 
271
 
        /**
272
 
           \brief Set as TXT record, with data \a texts
273
 
        */
274
 
        void setTxt(const QList<QByteArray> &texts);
275
 
 
276
 
        /**
277
 
           \brief Set as HINFO record, with data \a cpu and \a os
278
 
        */
279
 
        void setHinfo(const QByteArray &cpu, const QByteArray &os);
280
 
 
281
 
        /**
282
 
           \brief Set as NS record, with data \a name
283
 
        */
284
 
        void setNs(const QByteArray &name);
285
 
 
286
 
        /**
287
 
           \brief Set as NULL record, with data \a rawData
288
 
        */
289
 
        void setNull(const QByteArray &rawData);
290
 
 
291
 
private:
292
 
        class Private;
293
 
        QSharedDataPointer<Private> d;
294
 
};
295
 
 
296
 
class IRISNET_EXPORT ServiceInstance
297
 
{
298
 
public:
299
 
        ServiceInstance();
300
 
        ServiceInstance(const QString &instance, const QString &type, const QString &domain, const QMap<QString,QByteArray> &attributes);
301
 
        ServiceInstance(const ServiceInstance &from);
302
 
        ~ServiceInstance();
303
 
        ServiceInstance & operator=(const ServiceInstance &from);
304
 
 
305
 
        QString instance() const;
306
 
        QString type() const;
307
 
        QString domain() const;
308
 
        QMap<QString,QByteArray> attributes() const;
309
 
        QByteArray name() const; // full dns label
310
 
 
311
 
private:
312
 
        class Private;
313
 
        QSharedDataPointer<Private> d;
314
 
 
315
 
        friend class NameManager;
316
 
};
317
 
 
318
 
/**
319
 
   \brief Performs a DNS lookup
320
 
 
321
 
   NameResolver performs an asynchronous DNS lookup for a given domain name and record type.  Call start() to begin.  The resultsReady() signal is emitted on success, otherwise error() is emitted.  To cancel a lookup, call stop().
322
 
 
323
 
   For example, here is how to obtain the IPv4 addresses of a domain name:
324
 
\code
325
 
NameResolver *resolver;
326
 
 
327
 
void do_lookup()
328
 
{
329
 
        resolver = new NameResolver;
330
 
        connect(resolver, SIGNAL(resultsReady(const QList<XMPP::NameRecord> &)),
331
 
                SLOT(dns_resultsReady(const QList<XMPP::NameRecord> &)));
332
 
        connect(resolver, SIGNAL(error(XMPP::NameResolver::Error)),
333
 
                SLOT(dns_error(XMPP::NameResolver::Error)));
334
 
 
335
 
        // look up affinix.com
336
 
        resolver->start("affinix.com");
337
 
}
338
 
 
339
 
void dns_resultsReady(const QList<XMPP::NameRecord> &results)
340
 
{
341
 
        // print IP addresses
342
 
        foreach(NameRecord i, results)
343
 
                printf("%s\n", qPrintable(i.address().toString()));
344
 
}
345
 
 
346
 
void dns_error(XMPP::NameResolver::Error error)
347
 
{
348
 
        // handle error
349
 
        ...
350
 
}
351
 
\endcode
352
 
 
353
 
   Yes, a domain name can have multiple IP addresses.  Many applications ignore this fact, and use only one of the answers.  A proper network application should try connecting to each IP address until one succeeds.
354
 
 
355
 
   To lookup other types, pass the desired type to start().  For example, suppose you want to look up the MX record of a domain name:
356
 
 
357
 
\code
358
 
// look up the MX record for affinix.com
359
 
resolver->start("affinix.com", NameRecord::Mx);
360
 
\endcode
361
 
 
362
 
   It is also possible to perform long-lived queries.  This is generally useful for DNS Service Discovery.  Long-lived queries are continuous, and resultsReady() may be emitted multiple times.  Unlike a normal lookup, which stops once the results are returned, a long-lived query will keep going until stop() is called.
363
 
 
364
 
   For example, suppose you want to scan the local network for SSH services.  According to the DNS-SD protocol, this is done by querying for the name "_ssh._tcp.local." of type PTR.
365
 
 
366
 
\code
367
 
// monitor for SSH services on the local network
368
 
resolver->start("_ssh._tcp.local.", NameRecord::Ptr, NameResolver::LongLived);
369
 
\endcode
370
 
 
371
 
   Don't be alarmed by the trailing dot (".") character in this last example.  It is not well known, but all valid DNS domain names end with a dot.  However, NameResolver, like most DNS programming interfaces, allows the dot to be left out.  What this means is that if a trailing dot is missing in the input to start(), NameResolver will internally append one before performing the query.
372
 
 
373
 
   \sa NameRecord
374
 
*/
375
 
class IRISNET_EXPORT NameResolver : public QObject
376
 
{
377
 
        Q_OBJECT
378
 
public:
379
 
        /**
380
 
           \brief Resolve mode
381
 
        */
382
 
        enum Mode
383
 
        {
384
 
                Single,       ///< A normal DNS query with a single result set.
385
 
                LongLived     ///< An endless query, with multiple result sets allowed.
386
 
        };
387
 
 
388
 
        /**
389
 
           \brief Resolve error
390
 
        */
391
 
        enum Error
392
 
        {
393
 
                ErrorGeneric,     ///< General failure during lookup, no further details.
394
 
                ErrorNoName,      ///< Name does not exist.
395
 
                ErrorTimeout,     ///< The operation timed out.
396
 
                ErrorNoLocal,     ///< The query is to the local network, but no mechanism for Multicast DNS is available.
397
 
                ErrorNoLongLived  ///< The query requires long-lived capability, but no mechanism for doing so is available.
398
 
        };
399
 
 
400
 
        /**
401
 
           \brief Constructs a new resolver object with the given \a parent
402
 
        */
403
 
        NameResolver(QObject *parent = 0);
404
 
 
405
 
        /**
406
 
           \brief Destroys the resolver object
407
 
 
408
 
           The lookup is, of course, stopped.
409
 
        */
410
 
        ~NameResolver();
411
 
 
412
 
        /**
413
 
           \brief Starts a lookup
414
 
 
415
 
           A lookup for \a name of \a type is started.  For normal queries, \a mode should be NameResolver::Single (this is the default).  For long-lived queries, use NameResolver::LongLived.
416
 
 
417
 
           \sa stop
418
 
        */
419
 
        void start(const QByteArray &name, NameRecord::Type type = NameRecord::A, Mode mode = Single);
420
 
 
421
 
        /**
422
 
           \brief Stops a lookup
423
 
 
424
 
           Use this function if you want to stop the current lookup, such that the resolver object may be reused again later.  If you don't plan to reuse the object, then destroying the object is enough.
425
 
 
426
 
           \sa start
427
 
        */
428
 
        void stop();
429
 
 
430
 
signals:
431
 
        /**
432
 
           \brief Notification of result records
433
 
 
434
 
           This signal is emitted when results of the lookup operation have arrived.  The \a results parameter is a list of NameRecords.  All records will be of the type queried for with start(), unless the NameRecord::Any type was specified, in which case the records may be of any type
435
 
 
436
 
           When using the NameResolver::Single mode, the lookup is stopped once results are ready.  However, with the NameResolver::LongLived mode, the lookup stays active, and in that case this signal may be emitted multiple times.
437
 
        */
438
 
        void resultsReady(const QList<XMPP::NameRecord> &results);
439
 
 
440
 
        /**
441
 
           \brief Notification of error
442
 
 
443
 
           This signal is emitted if an error has occurred while performing a lookup.  The reason for error can be found in \a e.  Regardless of the mode used, the lookup is stopped when an error occurs.
444
 
        */
445
 
        void error(XMPP::NameResolver::Error e);
446
 
 
447
 
private:
448
 
        class Private;
449
 
        friend class Private;
450
 
        Private *d;
451
 
 
452
 
        friend class NameManager;
453
 
};
454
 
 
455
 
class IRISNET_EXPORT ServiceBrowser : public QObject
456
 
{
457
 
        Q_OBJECT
458
 
public:
459
 
        ServiceBrowser(QObject *parent = 0);
460
 
        ~ServiceBrowser();
461
 
 
462
 
        void start(const QString &type, const QString &domain = "local");
463
 
        void stop();
464
 
 
465
 
signals:
466
 
        void instanceAvailable(const XMPP::ServiceInstance &instance);
467
 
        void instanceUnavailable(const XMPP::ServiceInstance &instance);
468
 
        void error();
469
 
 
470
 
private:
471
 
        class Private;
472
 
        friend class Private;
473
 
        Private *d;
474
 
 
475
 
        friend class NameManager;
476
 
};
477
 
 
478
 
class IRISNET_EXPORT ServiceResolver : public QObject
479
 
{
480
 
        Q_OBJECT
481
 
public:
482
 
        ServiceResolver(QObject *parent = 0);
483
 
        ~ServiceResolver();
484
 
 
485
 
        void startFromInstance(const QByteArray &name);
486
 
        void startFromDomain(const QString &domain, const QString &type);
487
 
        void startFromPlain(const QString &host, int port); // non-SRV
488
 
        void tryNext();
489
 
        void stop();
490
 
 
491
 
signals:
492
 
        void resultsReady(const QHostAddress &address, int port);
493
 
        void finished();
494
 
        void error(); // SRV lookup failed
495
 
 
496
 
private:
497
 
        class Private;
498
 
        friend class Private;
499
 
        Private *d;
500
 
 
501
 
        friend class NameManager;
502
 
};
503
 
 
504
 
class IRISNET_EXPORT ServiceLocalPublisher : public QObject
505
 
{
506
 
        Q_OBJECT
507
 
public:
508
 
        enum Error
509
 
        {
510
 
                ErrorGeneric,  // generic error
511
 
                ErrorConflict, // name in use
512
 
                ErrorNoLocal   // unable to setup multicast dns
513
 
        };
514
 
 
515
 
        ServiceLocalPublisher(QObject *parent = 0);
516
 
        ~ServiceLocalPublisher();
517
 
 
518
 
        void publish(const QString &instance, const QString &type, int port, const QMap<QString,QByteArray> &attributes);
519
 
        void updateAttributes(const QMap<QString,QByteArray> &attributes);
520
 
        void addRecord(const NameRecord &rec);
521
 
        void cancel();
522
 
 
523
 
signals:
524
 
        void published();
525
 
        void error(XMPP::ServiceLocalPublisher::Error e);
526
 
 
527
 
private:
528
 
        class Private;
529
 
        friend class Private;
530
 
        Private *d;
531
 
 
532
 
        friend class NameManager;
533
 
};
534
 
 
535
 
}
536
 
 
537
 
#endif