JDNS
Loading...
Searching...
No Matches
Public Types | Signals | Public Member Functions | Static Public Member Functions | Friends | List of all members
QJDnsShared Class Reference

Abstraction layer on top of QJDns. More...

#include <qjdnsshared.h>

Inheritance diagram for QJDnsShared:

Public Types

enum  Mode { UnicastInternet , UnicastLocal , Multicast }
 The mode to operate in. More...
 

Signals

void shutdownFinished ()
 Indicates the object has been shut down.
 

Public Member Functions

 QJDnsShared (Mode mode, QObject *parent=0)
 Constructs a new object with the given mode and parent.
 
 ~QJDnsShared ()
 Destroys the object.
 
void setDebug (QJDnsSharedDebug *db, const QString &name)
 Sets the debug object to report to.
 
bool addInterface (const QHostAddress &addr)
 Adds an interface to operate on.
 
void removeInterface (const QHostAddress &addr)
 Removes a previously-added interface.
 
void shutdown ()
 Shuts down the object.
 

Static Public Member Functions

static QList< QByteArray > domains ()
 The domains to search in.
 
static void waitForShutdown (const QList< QJDnsShared * > &instances)
 Performs a blocking shutdown of many QJDnsShared instances.
 

Friends

class QJDnsSharedRequest
 
class QJDnsSharedPrivate
 

Detailed Description

Abstraction layer on top of QJDns.

Note
Iris users should utilize NetNames for DNS capabilities, not QJDnsShared. QJDnsShared is provided for non-Iris users (and it is also used internally by NetNames). To use QJDnsShared by itself, simply drop the jdnsshared.h and jdnsshared.cpp files, along with JDNS, into your project. It is not a full replacement for Qt's Q3Dns, as some tasks are left to you, but it covers most of it.

QJDns supports everything a typical application should ever need in DNS. However, it is expected that modern applications will need to maintain multiple QJDns instances at the same time, and this is where things can get complicated. For example, most applications will want at least two QJDns instances: one for IPv4 unicast and one for IPv6 unicast.

A single QJDnsShared object encapsulates multiple instances of QJDns that are related. For example, an IPv4 unicast instance and an IPv6 unicast instance could be coupled within QJDnsShared. Then, when a unicast operation is performed on the QJDnsShared object, both underlying instances will be queried as appropriate. The application would not need to perform two resolutions itself, nor deal with any related complexity.

Further, individual operations are performed using a separate class called QJDnsSharedRequest, eliminating the need for the application to directly interface with a central QJDns object or track integer handles. This makes it easier for individual parts of the application to "share" the same instance (or set of instances) of QJDns, hence the name.

QJDnsShared is a thin abstraction. QJDns subtypes (e.g. QJDns::Type, QJDns::Record, etc) are still used with QJDnsShared. Because of the duplication of documentation effort between NetNames and QJDns, there is no formal documentation for QJDns. Users of QJDnsShared will need to read qjdns.h, although a basic explanation of the elements can be found below.

Types:

QJDns::Type This is a convenience enumeration for common DNS record types. For example: A, Aaaa, Srv, etc. The values directly map to the integer values of the DNS protocol (e.g. Srv = 33). See qjdns.h for all of the types and values.
QJDns::Record This class holds a DNS record. The main fields are type (integer type, probably something listed in QJDns::Type), rdata (QByteArray of the record value), and haveKnown (boolean to indicate if a decoded form of the record value is also available). See qjdns.h for the possible known fields. You will most-likely always work with known types. Received records that have a type listed in QJDns::Type are guaranteed to be known and will provide a decoded value. If you are creating a record for publishing, you will need to set owner, ttl, and type. If the type to be published is listed in QJDns::Type, then you will need to set haveKnown to true and set the known fields as appropriate, otherwise you need to set rdata. You do not need to supply an encoded form in rdata for known types, it can be left empty in that case.
QJDns::PublishModeThis is for Multicast DNS, and can either be Unique or Shared. A shared record can be published by multiple owners (for example, a "_ssh._tcp.local." PTR record might resolve to many different SSH services owned by different machines). A unique record can only have one owner (for example, a "mycomputer.local." A record would resolve to the IP address of the machine that published it). Attempting to publish a record on a network where a unique record is already present will result in a conflict error.

Functions:

QJDns::detectPrimaryMulticast()Detects a multicast interface. Pass QHostAddress::Any or QHostAddress::AnyIPv6, depending on which type of interface is desired.

To use QJDnsShared, first create an instance of it, set it up by calling addInterface() as necessary, and then use QJDnsSharedRequest to perform operations on it.

Here is an example of how to create and set up a QJDnsShared object for typical DNS resolution:

// construct
// add IPv4 and IPv6 interfaces
dns->addInterface(QHostAddress::Any);
dns->addInterface(QHostAddress::AnyIPv6);
// at this point, the object is ready for operation
Abstraction layer on top of QJDns.
Definition: qjdnsshared.h:525
@ UnicastInternet
For regular DNS resolution.
Definition: qjdnsshared.h:537
bool addInterface(const QHostAddress &addr)
Adds an interface to operate on.

Perform a resolution like this:

connect(req, SIGNAL(resultsReady()), SLOT(req_resultsReady()));
req->query("psi-im.org", QJDns::A);
...
void req_resultsReady()
{
if(req->success())
{
// print all of the IP addresses obtained
QList<QJDns::Record> results = req->results();
foreach(QJDns::Record r, results)
{
if(r.type == QJDns::A)
printf("%s\n", qPrintable(r.address.toString());
}
}
else
printf("Error resolving!\n");
}
Performs a DNS operation using QJDnsShared.
Definition: qjdnsshared.h:236
void query(const QByteArray &name, int type)
Perform a query operation.
QList< QJDns::Record > results() const
Returns the results of the operation.
bool success() const
Indicates whether or not the operation was successful.
Definition: qjdns.h:100
QHostAddress address
for A, Aaaa
Definition: qjdns.h:109

It is important to filter the results as shown in the above example. QJDns guarantees at least one record in the results will be of the type queried for, but there may also be CNAME records present (of course, if the query was for a CNAME type, then the results will only be CNAME records). The recommended approach is to simply filter for the record types desired, as shown, rather than single out CNAME specifically.

When you are finished with a QJDnsShared object, it should be shut down before deleting:

connect(dns, SIGNAL(shutdownFinished()), SLOT(dns_shutdownFinished()));
dns->shutdown();
...
void dns_shutdownFinished()
{
delete dns;
}
void shutdownFinished()
Indicates the object has been shut down.
void shutdown()
Shuts down the object.

Setting up QJDnsShared for UnicastLocal and Multicast mode is done the same way as with UnicastInternet.

For example, here is how Multicast mode could be set up:

// construct
// add IPv4 interface
QHostAddress addr = QJDns::detectPrimaryMulticast(QHostAddress::Any);
dns->addInterface(addr);
// at this point, the object is ready for operation
@ Multicast
Multicast DNS querying and publishing.
Definition: qjdnsshared.h:552

QJDnsShared provides a lot of functionality, but certain aspects of DNS are deemed out of its scope. Below are the responsibilities of the user of QJDnsShared, if a more complete DNS behavior is desired:

Using a custom DNS implementation, such as QJDnsShared, has the drawback that it is difficult to take advantage of platform-specific features (for example, an OS-wide DNS cache or LDAP integration). An application strategy for normal DNS should probably be:

For Multicast DNS, awareness of the platform is doubly important. There should only be one Multicast DNS "Responder" per computer, and using QJDnsShared in Multicast mode at the same time could result in a conflict. An application strategy for Multicast DNS should be:

See also
QJDnsSharedRequest

Member Enumeration Documentation

◆ Mode

The mode to operate in.

Enumerator
UnicastInternet 

For regular DNS resolution.

In this mode, lookups are performed on all interfaces, and the first returned result is used.

UnicastLocal 

Perform regular DNS resolution using the Multicast DNS address.

This is used to resolve large and/or known Multicast DNS names without actually multicasting anything.

Multicast 

Multicast DNS querying and publishing.

Note
For Multicast mode, QJDnsShared supports up to one interface for each IP version (e.g. one IPv4 interface and one IPv6 interface), and expects the default/primary multicast interface for that IP version to be used.

Member Function Documentation

◆ addInterface()

bool QJDnsShared::addInterface ( const QHostAddress &  addr)

Adds an interface to operate on.

For UnicastInternet and UnicastLocal, these will almost always be QHostAddress::Any or QHostAddress::AnyIPv6 (operate on the default interface for IPv4 or IPv6, respectively).

For Multicast, it is expected that the default/primary multicast interface will be used here. Do not pass QHostAddress::Any (or AnyIPv6) with Multicast mode.

Returns true if the interface was successfully added, otherwise returns false.

◆ domains()

static QList< QByteArray > QJDnsShared::domains ( )
static

The domains to search in.

You should perform a separate resolution for every domain configured on this machine.

◆ setDebug()

void QJDnsShared::setDebug ( QJDnsSharedDebug db,
const QString &  name 
)

Sets the debug object to report to.

If a debug object is set using this function, then QJDnsShared will send output text to it, prefixing each line with name.

◆ shutdown()

void QJDnsShared::shutdown ( )

Shuts down the object.

This operation primarily exists for Multicast mode, so that any published records have a chance to be unpublished. If the QJDnsShared object is simply deleted without performing a shutdown, then published records will linger on the network until their TTLs expire.

When shutdown is complete, the shutdownFinished() signal will be emitted.

◆ waitForShutdown()

static void QJDnsShared::waitForShutdown ( const QList< QJDnsShared * > &  instances)
static

Performs a blocking shutdown of many QJDnsShared instances.

This function is a convenient way to shutdown multiple QJDnsShared instances synchronously. The internal shutdown procedure uses no more than a few cycles of the eventloop, so it should be safe to call without worry of the application being overly stalled. This function takes ownership of the instances passed to it, and will delete them upon completion.

It is worth noting that this function is implemented without the use of a nested eventloop. All of the QJDnsShared instances are moved into a temporary thread to perform the shutdown procedure, which should not cause any unexpected behavior in the current thread.

QList<QJDnsShared*> list;
list += jdnsShared_unicast;
list += jdnsShared_multicast;
// collect remaining debug information
QStringList finalDebugLines = jdnsSharedDebug.readDebugLines();
static void waitForShutdown(const QList< QJDnsShared * > &instances)
Performs a blocking shutdown of many QJDnsShared instances.

The documentation for this class was generated from the following file: