1/*
2 This file is part of the KDE project
3
4 SPDX-FileCopyrightText: 2004 Jakub Stachowski <qbast@go2.pl>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#ifndef KDNSSDSERVICEBASE_H
10#define KDNSSDSERVICEBASE_H
11
12#include "kdnssd_export.h"
13#include <QExplicitlySharedDataPointer>
14#include <QMap>
15#include <QString>
16#include <memory>
17
18/*!
19 * \namespace KDNSSD
20 * \inmodule KDNSSD
21 * \brief Interfaces to system mDNS service discovery.
22 */
23namespace KDNSSD
24{
25class ServiceBasePrivate;
26
27/*!
28 * \class KDNSSD::ServiceBase
29 * \inmodule KDNSSD
30 * \inheaderfile KDNSSD/ServiceBase
31 *
32 * \brief Describes a service.
33 *
34 * This class is used to describe a service. The service
35 * can be published by the current application (in which
36 * case it is probably a PublicService) or by
37 * another application, either on the current machine or
38 * a remote machine, in which case it is probably a
39 * RemoteService returned by ServiceBrowser.
40 *
41 * \note You should not normally need to create a ServiceBase
42 * object yourself.
43 *
44 * \sa PublicService
45 */
46class KDNSSD_EXPORT ServiceBase : public QSharedData // krazy:exclude=dpointer (protected)
47{
48public:
49 typedef QExplicitlySharedDataPointer<ServiceBase> Ptr;
50
51 /*!
52 * Creates a ServiceBase object
53 *
54 * Note that \a name, \a type and \a domain uniquely identify
55 * the service in the DNS-SD system, and \a host and \a port
56 * provide the actual location of the service.
57 *
58 * For example, RemoteService populates \a host and \a port
59 * based on the \a name, \a type and \a domain attributes
60 * using the DNS-SD resolution system.
61 *
62 * \a name is the service name
63 *
64 * \a type is the service type
65 *
66 * \a domain is the DNS-SD domain name for service
67 *
68 * \a host is the host name of the service (a fully-qualified domain name)
69 *
70 * \a port is the port number of the service
71 *
72 */
73 explicit ServiceBase(const QString &name = QString(),
74 const QString &type = QString(),
75 const QString &domain = QString(),
76 const QString &host = QString(),
77 unsigned short port = 0);
78
79 virtual ~ServiceBase();
80
81 /*!
82 * Returns the name of the service.
83 */
84 QString serviceName() const;
85
86 /*!
87 * Returns the type of the service.
88 *
89 * This is always in the format \c _sometype._udp or \c _sometype._tcp.
90 *
91 * See \l http://www.dns-sd.org for
92 * \l {http://www.dns-sd.org/ServiceTypes.html} {a full list of service types}.
93 */
94 QString type() const;
95
96 /*!
97 * Returns the domain that the service belongs to.
98 *
99 * It is "local." for link-local services.
100 */
101 QString domain() const;
102
103 /*!
104 * Returns the hostname of the service.
105 *
106 * Only valid for local and resolved remote services.
107 *
108 * Together with port(), this can be used to actually
109 * access the service.
110 *
111 * \sa RemoteService::resolve() and RemoteService::resolveAsync()
112 */
113 QString hostName() const;
114
115 /*!
116 * Returns the port number of the service.
117 *
118 * Only valid for local and resolved remote services.
119 *
120 * Together with hostName(), this can be used to actually
121 * access the service.
122 *
123 * \sa RemoteService::resolve() and RemoteService::resolveAsync()
124 */
125 unsigned short port() const;
126
127 /*!
128 * Returns additional text data associated with the service.
129 *
130 * Only valid for local and resolved remote services.
131 *
132 * This is data that provides additional information about the
133 * service. For example, it might be used to specify a printer
134 * queue on the printer server specified by hostName() and port().
135 *
136 * You can check for the data that might be associated with a
137 * particular service on the
138 * \l {http://www.dns-sd.org/ServiceTypes.html} {service types list}.
139 * If a \c key=value pair is given, this will appear with the \c value
140 * in a QByteArray indexed by the \c key. If the data is on its own
141 * (does not have an \c = in it), it will be used to index an empty
142 * QByteArray, and can be checked for with QMap::contains().
143 *
144 * For example, if you are accessing the _ipp._tcp service, you might
145 * do something like:
146 * \code
147 * QString printerModel = "unknown";
148 * if (service->textData().contains("ty")) {
149 * printQueue = QString::fromUtf8(service->textData()["ty"].constData());
150 * }
151 * \endcode
152 * since the TXT data of the IPP service may contain data like
153 * "ty=Apple LaserWriter Pro 630".
154 *
155 * \note You actually have to be
156 * a bit more clever than this, since the key should usually be case
157 * insensitive.
158 */
159 QMap<QString, QByteArray> textData() const;
160
161 /*!
162 * Compares services based on name, type and domain.
163 *
164 * This is enough to for unique identification and omitting
165 * port, host and text data allows to compare resolved and
166 * unresolved services
167 *
168 * \a o is the service to compare this service to
169 *
170 * Returns \c true if this service represents the same
171 * service (from the point of view of DNS-SD) as
172 * \a o, \c false otherwise
173 */
174 bool operator==(const ServiceBase &o) const;
175
176 /*!
177 * Compares services based on name, type and domain.
178 *
179 * This is enough to for unique identification and omitting
180 * port, host and text data allows to compare resolved and
181 * unresolved services
182 *
183 * \a o is the service to compare this service to
184 *
185 * Returns \c false if this service represents the same
186 * service (from the point of view of DNS-SD) as
187 * \a o, \c true otherwise
188 */
189 bool operator!=(const ServiceBase &o) const;
190
191protected:
192 KDNSSD_NO_EXPORT explicit ServiceBase(ServiceBasePrivate *const d);
193
194 virtual void virtual_hook(int, void *);
195
196protected:
197 std::unique_ptr<ServiceBasePrivate> const d;
198 // We cannot use Q_DECLARE_PRIVATE_D & Q_D here because of multiple inheritance with some
199 // of the subclasses of ServiceBasePrivate, where ServiceBasePrivate is not the first base class,
200 // so reinterpret_cast as used by the functions defined with Q_DECLARE_PRIVATE_D would fail.
201 // Using a custom macro here with static_cast would require to know about the type definition
202 // of the private classes, which we though want to avoid here in the public class.
203 // So instead some custom KDNSSD_D macros are used internally...
204};
205
206/* Utility functions */
207
208/*!
209 * \relates KDNSSD::ServiceBase
210 *
211 * Check if the \a domain is link-local.
212 *
213 * Returns \c true if domain is link-local ('local.'), \c false otherwise
214 */
215bool domainIsLocal(const QString &domain);
216
217}
218
219#endif
220

source code of kdnssd/src/servicebase.h