File indexing completed on 2024-04-28 15:22:07

0001 /*
0002     This file is part of the KDE project
0003 
0004     SPDX-FileCopyrightText: 2004 Jakub Stachowski <qbast@go2.pl>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #ifndef KDNSSDSERVICEBASE_H
0010 #define KDNSSDSERVICEBASE_H
0011 
0012 #include "kdnssd_export.h"
0013 #include <QExplicitlySharedDataPointer>
0014 #include <QMap>
0015 #include <QString>
0016 #include <memory>
0017 
0018 namespace KDNSSD
0019 {
0020 class ServiceBasePrivate;
0021 
0022 /**
0023  * @class ServiceBase servicebase.h KDNSSD/ServiceBase
0024  * @short Describes a service
0025  *
0026  * This class is used to describe a service. The service
0027  * can be published by the current application (in which
0028  * case it is probably a PublicService) or by
0029  * another application, either on the current machine or
0030  * a remote machine, in which case it is probably a
0031  * RemoteService returned by ServiceBrowser.
0032  *
0033  * You should not normally need to create a ServiceBase
0034  * object yourself.
0035  *
0036  * @author Jakub Stachowski
0037  *
0038  * @see PublicService
0039  */
0040 class KDNSSD_EXPORT ServiceBase : public QSharedData // krazy:exclude=dpointer (protected)
0041 {
0042 public:
0043     typedef QExplicitlySharedDataPointer<ServiceBase> Ptr;
0044 
0045     /**
0046      * Creates a ServiceBase object
0047      *
0048      * Note that @p name, @p type and @p domain uniquely identify
0049      * the service in the DNS-SD system, and @p host and @p port
0050      * provide the actual location of the service.
0051      *
0052      * For example, RemoteService populates @p host and @p port
0053      * based on the @p name, @p type and @p domain attributes
0054      * using the DNS-SD resolution system.
0055      *
0056      * @param name   service name
0057      * @param type   service type
0058      * @param domain the DNS-SD domain name for service
0059      * @param host   the host name of the service (a fully-qualified domain name)
0060      * @param port   the port number of the service
0061      */
0062     explicit ServiceBase(const QString &name = QString(),
0063                          const QString &type = QString(),
0064                          const QString &domain = QString(),
0065                          const QString &host = QString(),
0066                          unsigned short port = 0);
0067 
0068     virtual ~ServiceBase();
0069 
0070     /**
0071      * The name of the service
0072      */
0073     QString serviceName() const;
0074 
0075     /**
0076      * The type of the service
0077      *
0078      * This is always in the format _sometype._udp or _sometype._tcp.
0079      *
0080      * See the <a href="http://www.dns-sd.org">DNS-SD website</a> for
0081      * <a href="http://www.dns-sd.org/ServiceTypes.html">a full list of service types</a>.
0082      */
0083     QString type() const;
0084 
0085     /**
0086      * The domain that the service belongs to
0087      *
0088      * It is "local." for link-local services.
0089      */
0090     QString domain() const;
0091 
0092     /**
0093      * The hostname of the service
0094      *
0095      * Only valid for local and resolved remote services.
0096      *
0097      * Together with port(), this can be used to actually
0098      * access the service.
0099      *
0100      * @see RemoteService::resolve() and RemoteService::resolveAsync()
0101      */
0102     QString hostName() const;
0103 
0104     /**
0105      * The port number of the service
0106      *
0107      * Only valid for local and resolved remote services.
0108      *
0109      * Together with hostName(), this can be used to actually
0110      * access the service.
0111      *
0112      * @see RemoteService::resolve() and RemoteService::resolveAsync()
0113      */
0114     unsigned short port() const;
0115 
0116     /**
0117      * Additional text data associated with the service
0118      *
0119      * Only valid for local and resolved remote services.
0120      *
0121      * This is data that provides additional information about the
0122      * service.  For example, it might be used to specify a printer
0123      * queue on the printer server specified by hostName() and port().
0124      *
0125      * You can check for the data that might be associated with a
0126      * particular service on the <a
0127      * href="http://www.dns-sd.org/ServiceTypes.html">service types list</a>.
0128      * If a @c key=value pair is given, this will appear with the @c value
0129      * in a QByteArray indexed by the @c key.  If the data is on its own
0130      * (does not have an @c = in it), it will be used to index an empty
0131      * QByteArray, and can be checked for with QMap::contains().
0132      *
0133      * For example, if you are accessing the _ipp._tcp service, you might
0134      * do something like
0135      * @code
0136      * QString printerModel = "unknown";
0137      * if (service->textData().contains("ty")) {
0138      *     printQueue = QString::fromUtf8(service->textData()["ty"].constData());
0139      * }
0140      * @endcode
0141      * since the TXT data of the IPP service may contain data like
0142      * "ty=Apple LaserWriter Pro 630".  Note that you actually have to be
0143      * a bit more clever than this, since the key should usually be case
0144      * insensitive.
0145      */
0146     QMap<QString, QByteArray> textData() const;
0147 
0148     /**
0149      * Compares services based on name, type and domain
0150      *
0151      * This is enough to for unique identification and omitting
0152      * port, host and text data allows to compare resolved and
0153      * unresolved services
0154      *
0155      * @param o the service to compare this service to
0156      * @return @c true if this service represents the same
0157      *         service (from the point of view of DNS-SD) as
0158      *         @p o, @c false otherwise
0159      */
0160     bool operator==(const ServiceBase &o) const;
0161     /**
0162      * Compares services based on name, type and domain
0163      *
0164      * This is enough to for unique identification and omitting
0165      * port, host and text data allows to compare resolved and
0166      * unresolved services
0167      *
0168      * @param o the service to compare this service to
0169      * @return @c false if this service represents the same
0170      *         service (from the point of view of DNS-SD) as
0171      *         @p o, @c true otherwise
0172      */
0173     bool operator!=(const ServiceBase &o) const;
0174 
0175 protected:
0176     KDNSSD_NO_EXPORT explicit ServiceBase(ServiceBasePrivate *const d);
0177 
0178     virtual void virtual_hook(int, void *);
0179 
0180 protected:
0181     std::unique_ptr<ServiceBasePrivate> const d;
0182     // We cannot use Q_DECLARE_PRIVATE_D & Q_D here because of multiple inheritance with some
0183     // of the subclasses of ServiceBasePrivate, where ServiceBasePrivate is not the first base class,
0184     // so reinterpret_cast as used by the functions defined with Q_DECLARE_PRIVATE_D would fail.
0185     // Using a custom macro here with static_cast would require to know about the type definition
0186     // of the private classes, which we though want to avoid here in the public class.
0187     // So instead some custom KDNSSD_D macros are used internally...
0188 };
0189 
0190 /* Utility functions */
0191 
0192 /**
0193  * Check if the domain is link-local
0194  *
0195  * @return @c true if domain is link-local ('local.'), @c false otherwise
0196  */
0197 bool domainIsLocal(const QString &domain);
0198 
0199 }
0200 
0201 #endif