diff --git a/LICENSES/BSD-3-Clause.txt b/LICENSES/BSD-3-Clause.txt new file mode 100644 index 0000000..0741db7 --- /dev/null +++ b/LICENSES/BSD-3-Clause.txt @@ -0,0 +1,26 @@ +Copyright (c) . All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/LGPL-2.0-or-later.txt b/LICENSES/LGPL-2.0-or-later.txt new file mode 100644 index 0000000..5c96471 --- /dev/null +++ b/LICENSES/LGPL-2.0-or-later.txt @@ -0,0 +1,446 @@ +GNU LIBRARY GENERAL PUBLIC LICENSE + +Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. + +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is numbered 2 because +it goes with version 2 of the ordinary GPL.] + +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public Licenses are intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. + +This license, the Library General Public License, applies to some specially +designated Free Software Foundation software, and to any other libraries whose +authors decide to use it. You can use it for your libraries, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom +to distribute copies of free software (and charge for this service if you +wish), that you receive source code or can get it if you want it, that you +can change the software or use pieces of it in new free programs; and that +you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to +deny you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of +the library, or if you modify it. + +For example, if you distribute copies of the library, whether gratis or for +a fee, you must give the recipients all the rights that we gave you. You must +make sure that they, too, receive or can get the source code. If you link +a program with the library, you must provide complete object files to the +recipients so that they can relink them with the library, after making changes +to the library and recompiling it. And you must show them these terms so they +know their rights. + +Our method of protecting your rights has two steps: (1) copyright the library, +and (2) offer you this license which gives you legal permission to copy, distribute +and/or modify the library. + +Also, for each distributor's protection, we want to make certain that everyone +understands that there is no warranty for this free library. If the library +is modified by someone else and passed on, we want its recipients to know +that what they have is not the original version, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that companies distributing free software will individually +obtain patent licenses, thus in effect transforming the program into proprietary +software. To prevent this, we have made it clear that any patent must be licensed +for everyone's free use or not licensed at all. + +Most GNU software, including some libraries, is covered by the ordinary GNU +General Public License, which was designed for utility programs. This license, +the GNU Library General Public License, applies to certain designated libraries. +This license is quite different from the ordinary one; be sure to read it +in full, and don't assume that anything in it is the same as in the ordinary +license. + +The reason we have a separate public license for some libraries is that they +blur the distinction we usually make between modifying or adding to a program +and simply using it. Linking a program with a library, without changing the +library, is in some sense simply using the library, and is analogous to running +a utility program or application program. However, in a textual and legal +sense, the linked executable is a combined work, a derivative of the original +library, and the ordinary General Public License treats it as such. + +Because of this blurred distinction, using the ordinary General Public License +for libraries did not effectively promote software sharing, because most developers +did not use the libraries. We concluded that weaker conditions might promote +sharing better. + +However, unrestricted linking of non-free programs would deprive the users +of those programs of all benefit from the free status of the libraries themselves. +This Library General Public License is intended to permit developers of non-free +programs to use free libraries, while preserving your freedom as a user of +such programs to change the free libraries that are incorporated in them. +(We have not seen how to achieve this as regards changes in header files, +but we have achieved it as regards changes in the actual functions of the +Library.) The hope is that this will lead to faster development of free libraries. + +The precise terms and conditions for copying, distribution and modification +follow. Pay close attention to the difference between a "work based on the +library" and a "work that uses the library". The former contains code derived +from the library, while the latter only works together with the library. + +Note that it is possible for a library to be covered by the ordinary General +Public License rather than by this special one. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License Agreement applies to any software library which contains a +notice placed by the copyright holder or other authorized party saying it +may be distributed under the terms of this Library General Public License +(also called "this License"). Each licensee is addressed as "you". + +A "library" means a collection of software functions and/or data prepared +so as to be conveniently linked with application programs (which use some +of those functions and data) to form executables. + +The "Library", below, refers to any such software library or work which has +been distributed under these terms. A "work based on the Library" means either +the Library or any derivative work under copyright law: that is to say, a +work containing the Library or a portion of it, either verbatim or with modifications +and/or translated straightforwardly into another language. (Hereinafter, translation +is included without limitation in the term "modification".) + +"Source code" for a work means the preferred form of the work for making modifications +to it. For a library, complete source code means all the source code for all +modules it contains, plus any associated interface definition files, plus +the scripts used to control compilation and installation of the library. + +Activities other than copying, distribution and modification are not covered +by this License; they are outside its scope. The act of running a program +using the Library is not restricted, and output from such a program is covered +only if its contents constitute a work based on the Library (independent of +the use of the Library in a tool for writing it). Whether that is true depends +on what the Library does and what the program that uses the Library does. + +1. You may copy and distribute verbatim copies of the Library's complete source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and disclaimer +of warranty; keep intact all the notices that refer to this License and to +the absence of any warranty; and distribute a copy of this License along with +the Library. + +You may charge a fee for the physical act of transferring a copy, and you +may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Library or any portion of it, +thus forming a work based on the Library, and copy and distribute such modifications +or work under the terms of Section 1 above, provided that you also meet all +of these conditions: + + a) The modified work must itself be a software library. + +b) You must cause the files modified to carry prominent notices stating that +you changed the files and the date of any change. + +c) You must cause the whole of the work to be licensed at no charge to all +third parties under the terms of this License. + +d) If a facility in the modified Library refers to a function or a table of +data to be supplied by an application program that uses the facility, other +than as an argument passed when the facility is invoked, then you must make +a good faith effort to ensure that, in the event an application does not supply +such function or table, the facility still operates, and performs whatever +part of its purpose remains meaningful. + +(For example, a function in a library to compute square roots has a purpose +that is entirely well-defined independent of the application. Therefore, Subsection +2d requires that any application-supplied function or table used by this function +must be optional: if the application does not supply it, the square root function +must still compute square roots.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Library, and can be reasonably +considered independent and separate works in themselves, then this License, +and its terms, do not apply to those sections when you distribute them as +separate works. But when you distribute the same sections as part of a whole +which is a work based on the Library, the distribution of the whole must be +on the terms of this License, whose permissions for other licensees extend +to the entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise +the right to control the distribution of derivative or collective works based +on the Library. + +In addition, mere aggregation of another work not based on the Library with +the Library (or with a work based on the Library) on a volume of a storage +or distribution medium does not bring the other work under the scope of this +License. + +3. You may opt to apply the terms of the ordinary GNU General Public License +instead of this License to a given copy of the Library. To do this, you must +alter all the notices that refer to this License, so that they refer to the +ordinary GNU General Public License, version 2, instead of to this License. +(If a newer version than version 2 of the ordinary GNU General Public License +has appeared, then you can specify that version instead if you wish.) Do not +make any other change in these notices. + +Once this change is made in a given copy, it is irreversible for that copy, +so the ordinary GNU General Public License applies to all subsequent copies +and derivative works made from that copy. + +This option is useful when you wish to copy part of the code of the Library +into a program that is not a library. + +4. You may copy and distribute the Library (or a portion or derivative of +it, under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you accompany it with the complete corresponding +machine-readable source code, which must be distributed under the terms of +Sections 1 and 2 above on a medium customarily used for software interchange. + +If distribution of object code is made by offering access to copy from a designated +place, then offering equivalent access to copy the source code from the same +place satisfies the requirement to distribute the source code, even though +third parties are not compelled to copy the source along with the object code. + +5. A program that contains no derivative of any portion of the Library, but +is designed to work with the Library by being compiled or linked with it, +is called a "work that uses the Library". Such a work, in isolation, is not +a derivative work of the Library, and therefore falls outside the scope of +this License. + +However, linking a "work that uses the Library" with the Library creates an +executable that is a derivative of the Library (because it contains portions +of the Library), rather than a "work that uses the library". The executable +is therefore covered by this License. Section 6 states terms for distribution +of such executables. + +When a "work that uses the Library" uses material from a header file that +is part of the Library, the object code for the work may be a derivative work +of the Library even though the source code is not. Whether this is true is +especially significant if the work can be linked without the Library, or if +the work is itself a library. The threshold for this to be true is not precisely +defined by law. + +If such an object file uses only numerical parameters, data structure layouts +and accessors, and small macros and small inline functions (ten lines or less +in length), then the use of the object file is unrestricted, regardless of +whether it is legally a derivative work. (Executables containing this object +code plus portions of the Library will still fall under Section 6.) + +Otherwise, if the work is a derivative of the Library, you may distribute +the object code for the work under the terms of Section 6. Any executables +containing that work also fall under Section 6, whether or not they are linked +directly with the Library itself. + +6. As an exception to the Sections above, you may also compile or link a "work +that uses the Library" with the Library to produce a work containing portions +of the Library, and distribute that work under terms of your choice, provided +that the terms permit modification of the work for the customer's own use +and reverse engineering for debugging such modifications. + +You must give prominent notice with each copy of the work that the Library +is used in it and that the Library and its use are covered by this License. +You must supply a copy of this License. If the work during execution displays +copyright notices, you must include the copyright notice for the Library among +them, as well as a reference directing the user to the copy of this License. +Also, you must do one of these things: + +a) Accompany the work with the complete corresponding machine-readable source +code for the Library including whatever changes were used in the work (which +must be distributed under Sections 1 and 2 above); and, if the work is an +executable linked with the Library, with the complete machine-readable "work +that uses the Library", as object code and/or source code, so that the user +can modify the Library and then relink to produce a modified executable containing +the modified Library. (It is understood that the user who changes the contents +of definitions files in the Library will not necessarily be able to recompile +the application to use the modified definitions.) + +b) Accompany the work with a written offer, valid for at least three years, +to give the same user the materials specified in Subsection 6a, above, for +a charge no more than the cost of performing this distribution. + +c) If distribution of the work is made by offering access to copy from a designated +place, offer equivalent access to copy the above specified materials from +the same place. + +d) Verify that the user has already received a copy of these materials or +that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the Library" must +include any data and utility programs needed for reproducing the executable +from it. However, as a special exception, the source code distributed need +not include anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the operating +system on which the executable runs, unless that component itself accompanies +the executable. + +It may happen that this requirement contradicts the license restrictions of +other proprietary libraries that do not normally accompany the operating system. +Such a contradiction means you cannot use both them and the Library together +in an executable that you distribute. + +7. You may place library facilities that are a work based on the Library side-by-side +in a single library together with other library facilities not covered by +this License, and distribute such a combined library, provided that the separate +distribution of the work based on the Library and of the other library facilities +is otherwise permitted, and provided that you do these two things: + +a) Accompany the combined library with a copy of the same work based on the +Library, uncombined with any other library facilities. This must be distributed +under the terms of the Sections above. + +b) Give prominent notice with the combined library of the fact that part of +it is a work based on the Library, and explaining where to find the accompanying +uncombined form of the same work. + +8. You may not copy, modify, sublicense, link with, or distribute the Library +except as expressly provided under this License. Any attempt otherwise to +copy, modify, sublicense, link with, or distribute the Library is void, and +will automatically terminate your rights under this License. However, parties +who have received copies, or rights, from you under this License will not +have their licenses terminated so long as such parties remain in full compliance. + +9. You are not required to accept this License, since you have not signed +it. However, nothing else grants you permission to modify or distribute the +Library or its derivative works. These actions are prohibited by law if you +do not accept this License. Therefore, by modifying or distributing the Library +(or any work based on the Library), you indicate your acceptance of this License +to do so, and all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + +10. Each time you redistribute the Library (or any work based on the Library), +the recipient automatically receives a license from the original licensor +to copy, distribute, link with or modify the Library subject to these terms +and conditions. You may not impose any further restrictions on the recipients' +exercise of the rights granted herein. You are not responsible for enforcing +compliance by third parties to this License. + +11. If, as a consequence of a court judgment or allegation of patent infringement +or for any other reason (not limited to patent issues), conditions are imposed +on you (whether by court order, agreement or otherwise) that contradict the +conditions of this License, they do not excuse you from the conditions of +this License. If you cannot distribute so as to satisfy simultaneously your +obligations under this License and any other pertinent obligations, then as +a consequence you may not distribute the Library at all. For example, if a +patent license would not permit royalty-free redistribution of the Library +by all those who receive copies directly or indirectly through you, then the +only way you could satisfy both it and this License would be to refrain entirely +from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents +or other property right claims or to contest validity of any such claims; +this section has the sole purpose of protecting the integrity of the free +software distribution system which is implemented by public license practices. +Many people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose +that choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +12. If the distribution and/or use of the Library is restricted in certain +countries either by patents or by copyrighted interfaces, the original copyright +holder who places the Library under this License may add an explicit geographical +distribution limitation excluding those countries, so that distribution is +permitted only in or among countries not thus excluded. In such case, this +License incorporates the limitation as if written in the body of this License. + +13. The Free Software Foundation may publish revised and/or new versions of +the Library General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to address +new problems or concerns. + +Each version is given a distinguishing version number. If the Library specifies +a version number of this License which applies to it and "any later version", +you have the option of following the terms and conditions either of that version +or of any later version published by the Free Software Foundation. If the +Library does not specify a license version number, you may choose any version +ever published by the Free Software Foundation. + +14. If you wish to incorporate parts of the Library into other free programs +whose distribution conditions are incompatible with these, write to the author +to ask for permission. For software which is copyrighted by the Free Software +Foundation, write to the Free Software Foundation; we sometimes make exceptions +for this. Our decision will be guided by the two goals of preserving the free +status of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + +15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY +"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE +OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE +THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE +OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA +OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES +OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH +HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible +use to the public, we recommend making it free software that everyone can +redistribute and change. You can do so by permitting redistribution under +these terms (or, alternatively, under the terms of the ordinary General Public +License). + +To apply these terms, attach the following notices to the library. It is safest +to attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the "copyright" +line and a pointer to where the full notice is found. + +one line to give the library's name and an idea of what it does. + +Copyright (C) year name of author + +This library is free software; you can redistribute it and/or modify it under +the terms of the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your option) +any later version. + +This library is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +details. + +You should have received a copy of the GNU Library General Public License +along with this library; if not, write to the Free Software Foundation, Inc., +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the library, if necessary. Here +is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in + +the library `Frob' (a library for tweaking knobs) written + +by James Random Hacker. + +signature of Ty Coon, 1 April 1990 + +Ty Coon, President of Vice + +That's all there is to it! diff --git a/cmake/FindAvahi.cmake b/cmake/FindAvahi.cmake index 5515ee7..e96d5e6 100644 --- a/cmake/FindAvahi.cmake +++ b/cmake/FindAvahi.cmake @@ -1,36 +1,14 @@ # Find Avahi. Only avahi-common/defs.h is really needed -# Copyright (c) 2007, Jakub Stachowski, +# SPDX-FileCopyrightText: 2007 Jakub Stachowski # -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# SPDX-License-Identifier: BSD-3-Clause find_path(AVAHI_INCLUDE_DIR avahi-common/defs.h) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Avahi DEFAULT_MSG AVAHI_INCLUDE_DIR) mark_as_advanced(AVAHI_INCLUDE_DIR) diff --git a/cmake/FindDNSSD.cmake b/cmake/FindDNSSD.cmake index 3980312..e817a51 100644 --- a/cmake/FindDNSSD.cmake +++ b/cmake/FindDNSSD.cmake @@ -1,72 +1,50 @@ # - Try to find DNSSD # Once done this will define # # DNSSD_FOUND - system has DNSSD # DNSSD_INCLUDE_DIR - the DNSSD include directory # DNSSD_LIBRARIES - Link these to use dnssd # DNSSD_DEFINITIONS - Compiler switches required for using DNSSD # # need more test: look at into dnssd/configure.in.in -# Copyright (c) 2006, Laurent Montel, +# SPDX-FileCopyrightText: 2006 Laurent Montel # -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# SPDX-License-Identifier: BSD-3-Clause include(CMakePushCheckState) include(CheckFunctionExists) FIND_PATH(DNSSD_INCLUDE_DIR dns_sd.h /usr/include/avahi-compat-libdns_sd/ ) if (DNSSD_INCLUDE_DIR) if (APPLE) set(DNSSD_LIBRARIES "/usr/lib/libSystem.dylib") else (APPLE) FIND_LIBRARY(DNSSD_LIBRARIES NAMES dns_sd ) endif (APPLE) cmake_push_check_state() set(CMAKE_REQUIRED_INCLUDES ${DNSSD_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${DNSSD_LIBRARIES}) CHECK_FUNCTION_EXISTS(DNSServiceRefDeallocate DNSSD_FUNCTION_FOUND) cmake_pop_check_state() if (DNSSD_INCLUDE_DIR AND DNSSD_LIBRARIES AND DNSSD_FUNCTION_FOUND) set(DNSSD_FOUND TRUE) endif (DNSSD_INCLUDE_DIR AND DNSSD_LIBRARIES AND DNSSD_FUNCTION_FOUND) endif (DNSSD_INCLUDE_DIR) if (DNSSD_FOUND) if (NOT DNSSD_FIND_QUIETLY) message(STATUS "Found DNSSD: ${DNSSD_LIBRARIES}") endif (NOT DNSSD_FIND_QUIETLY) else (DNSSD_FOUND) if (DNSSD_FIND_REQUIRED) message(FATAL_ERROR "Could NOT find DNSSD") endif (DNSSD_FIND_REQUIRED) endif (DNSSD_FOUND) MARK_AS_ADVANCED(DNSSD_INCLUDE_DIR DNSSD_LIBRARIES) diff --git a/src/avahi-domainbrowser.cpp b/src/avahi-domainbrowser.cpp index 9f09a70..2157a18 100644 --- a/src/avahi-domainbrowser.cpp +++ b/src/avahi-domainbrowser.cpp @@ -1,182 +1,170 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * Copyright (C) 2018 Harald Sitter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + SPDX-FileCopyrightText: 2018 Harald Sitter + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "avahi-domainbrowser_p.h" #include #include #include #include #include #include "avahi_server_interface.h" #include "domainbrowser.h" #include "avahi_domainbrowser_interface.h" namespace KDNSSD { DomainBrowser::DomainBrowser(DomainType type, QObject *parent) : QObject(parent), d(new DomainBrowserPrivate(type, this)) {} DomainBrowser::~DomainBrowser() { delete d; } void DomainBrowser::startBrowse() { if (d->m_started) { return; } d->m_started = true; // Do not race! // https://github.com/lathiat/avahi/issues/9 // Avahi's DBus API is incredibly racey with signals getting fired // immediately after a request was made even though we may not yet be // listening. In lieu of a proper upstream fix for this we'll unfortunately // have to resort to this hack: // We register to all signals regardless of path and then filter them once // we know what "our" path is. This is much more fragile than a proper // QDBusInterface assisted signal connection but unfortunately the only way // we can reliably prevent signals getting lost in the race. // This uses a fancy trick whereby using QDBusMessage as last argument will // give us the correct signal argument types as well as the underlying // message so that we may check the message path. QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.DomainBrowser", "ItemNew", d, SLOT(gotGlobalItemNew(int,int,QString,uint,QDBusMessage))); QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.DomainBrowser", "ItemRemove", d, SLOT(gotGlobalItemRemove(int,int,QString,uint,QDBusMessage))); QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.DomainBrowser", "AllForNow", d, SLOT(gotGlobalAllForNow(QDBusMessage))); d->m_dbusObjectPath.clear(); org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus()); QDBusReply rep = s.DomainBrowserNew(-1, -1, QString(), (d->m_type == Browsing) ? AVAHI_DOMAIN_BROWSER_BROWSE : AVAHI_DOMAIN_BROWSER_REGISTER, 0); if (!rep.isValid()) { return; } d->m_dbusObjectPath = rep.value().path(); // This is held because we need to explicitly Free it! d->m_browser = new org::freedesktop::Avahi::DomainBrowser( s.service(), d->m_dbusObjectPath, s.connection()); if (d->m_type == Browsing) { QString domains_evar = QString::fromLocal8Bit(qgetenv("AVAHI_BROWSE_DOMAINS")); if (!domains_evar.isEmpty()) { const QStringList edomains = domains_evar.split(QLatin1Char(':')); for (const QString &s : edomains) { d->gotNewDomain(-1, -1, s, 0); } } //FIXME: watch this file and restart browser if it changes QString confDir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QFile domains_cfg(confDir + QStringLiteral("/avahi/browse-domains")); if (domains_cfg.open(QIODevice::ReadOnly | QIODevice::Text)) while (!domains_cfg.atEnd()) { d->gotNewDomain(-1, -1, QString::fromUtf8(domains_cfg.readLine().data()).trimmed(), 0); } } } void DomainBrowserPrivate::gotGlobalItemNew(int interface, int protocol, const QString &domain, uint flags, QDBusMessage msg) { if (!isOurMsg(msg)) { return; } gotNewDomain(interface, protocol, domain, flags); } void DomainBrowserPrivate::gotGlobalItemRemove(int interface, int protocol, const QString &domain, uint flags, QDBusMessage msg) { if (!isOurMsg(msg)) { return; } gotRemoveDomain(interface, protocol, domain, flags); } void DomainBrowserPrivate::gotGlobalAllForNow(QDBusMessage msg) { if (!isOurMsg(msg)) { return; } } void DomainBrowserPrivate::gotNewDomain(int, int, const QString &domain, uint) { QString decoded = DNSToDomain(domain); if (m_domains.contains(decoded)) { return; } m_domains += decoded; emit m_parent->domainAdded(decoded); } void DomainBrowserPrivate::gotRemoveDomain(int, int, const QString &domain, uint) { QString decoded = DNSToDomain(domain); if (!m_domains.contains(decoded)) { return; } emit m_parent->domainRemoved(decoded); m_domains.remove(decoded); } QStringList DomainBrowser::domains() const { return d->m_domains.values(); } bool DomainBrowser::isRunning() const { return d->m_started; } } #include "moc_domainbrowser.cpp" #include "moc_avahi-domainbrowser_p.cpp" diff --git a/src/avahi-domainbrowser_p.h b/src/avahi-domainbrowser_p.h index ce65ada..70c39d5 100644 --- a/src/avahi-domainbrowser_p.h +++ b/src/avahi-domainbrowser_p.h @@ -1,70 +1,58 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef AVAHI_DOMAINBROWSER_P_H #define AVAHI_DOMAINBROWSER_P_H #include #include "domainbrowser.h" #include "avahi_listener_p.h" #include "avahi_domainbrowser_interface.h" namespace KDNSSD { class DomainBrowserPrivate : public QObject, public AvahiListener { Q_OBJECT public: DomainBrowserPrivate(DomainBrowser::DomainType type, DomainBrowser *parent) : m_type(type), m_browser(nullptr), m_parent(parent), m_started(false) {} ~DomainBrowserPrivate() { if (m_browser) { m_browser->Free(); } } DomainBrowser::DomainType m_type; org::freedesktop::Avahi::DomainBrowser *m_browser = nullptr; DomainBrowser *m_parent = nullptr; bool m_started = false; QSet m_domains; public Q_SLOTS: // NB: The global slots are runtime connected! If their signature changes // make sure the SLOT() signature gets updated! void gotGlobalItemNew(int interface, int protocol, const QString &domain, uint flags, QDBusMessage msg); void gotGlobalItemRemove(int interface, int protocol, const QString &domain, uint flags, QDBusMessage msg); void gotGlobalAllForNow(QDBusMessage msg); void gotNewDomain(int, int, const QString &, uint); void gotRemoveDomain(int, int, const QString &, uint); }; } #endif diff --git a/src/avahi-publicservice.cpp b/src/avahi-publicservice.cpp index 35118e7..3108ad9 100644 --- a/src/avahi-publicservice.cpp +++ b/src/avahi-publicservice.cpp @@ -1,324 +1,312 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004, 2005 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004, 2005 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "avahi-publicservice_p.h" #include #include #include "publicservice.h" #include #if HAVE_SYS_TYPES_H #include #endif #include "servicebrowser.h" #include "avahi_server_interface.h" #include "avahi_entrygroup_interface.h" namespace KDNSSD { PublicService::PublicService(const QString &name, const QString &type, unsigned int port, const QString &domain, const QStringList &subtypes) : QObject(), ServiceBase(new PublicServicePrivate(this, name, type, domain, port)) { K_D; if (domain.isNull()) { d->m_domain = "local."; } d->m_subtypes = subtypes; } PublicService::~PublicService() { stop(); } void PublicServicePrivate::tryApply() { if (fillEntryGroup()) { commit(); } else { m_parent->stop(); emit m_parent->published(false); } } void PublicServicePrivate::gotGlobalStateChanged(int state, const QString &error, QDBusMessage msg) { if (!isOurMsg(msg)) { return; } groupStateChanged(state, error); } void PublicService::setServiceName(const QString &serviceName) { K_D; d->m_serviceName = serviceName; if (d->m_running) { d->m_group->Reset(); d->tryApply(); } } void PublicService::setDomain(const QString &domain) { K_D; d->m_domain = domain; if (d->m_running) { d->m_group->Reset(); d->tryApply(); } } void PublicService::setType(const QString &type) { K_D; d->m_type = type; if (d->m_running) { d->m_group->Reset(); d->tryApply(); } } void PublicService::setSubTypes(const QStringList &subtypes) { K_D; d->m_subtypes = subtypes; if (d->m_running) { d->m_group->Reset(); d->tryApply(); } } QStringList PublicService::subtypes() const { K_D; return d->m_subtypes; } void PublicService::setPort(unsigned short port) { K_D; d->m_port = port; if (d->m_running) { d->m_group->Reset(); d->tryApply(); } } void PublicService::setTextData(const QMap &textData) { K_D; d->m_textData = textData; if (d->m_running) { d->m_group->Reset(); d->tryApply(); } } bool PublicService::isPublished() const { K_D; return d->m_published; } bool PublicService::publish() { K_D; publishAsync(); while (d->m_running && !d->m_published) { QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } return d->m_published; } void PublicService::stop() { K_D; if (d->m_group) { d->m_group->Reset(); } d->m_running = false; d->m_published = false; } bool PublicServicePrivate::fillEntryGroup() { registerTypes(); if (!m_group) { // Do not race! // https://github.com/lathiat/avahi/issues/9 // Avahi's DBus API is incredibly racey with signals getting fired // immediately after a request was made even though we may not yet be // listening. In lieu of a proper upstream fix for this we'll unfortunately // have to resort to this hack: // We register to all signals regardless of path and then filter them once // we know what "our" path is. This is much more fragile than a proper // QDBusInterface assisted signal connection but unfortunately the only way // we can reliably prevent signals getting lost in the race. // This uses a fancy trick whereby using QDBusMessage as last argument will // give us the correct signal argument types as well as the underlying // message so that we may check the message path. QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.EntryGroup", "StateChanged", this, SLOT(gotGlobalStateChanged(int,QString,QDBusMessage))); m_dbusObjectPath.clear(); QDBusReply rep = m_server->EntryGroupNew(); if (!rep.isValid()) { return false; } m_dbusObjectPath = rep.value().path(); m_group = new org::freedesktop::Avahi::EntryGroup("org.freedesktop.Avahi", m_dbusObjectPath, QDBusConnection::systemBus()); } if (m_serviceName.isNull()) { QDBusReply rep = m_server->GetHostName(); if (!rep.isValid()) { return false; } m_serviceName = rep.value(); } QList txt; QMap::ConstIterator itEnd = m_textData.constEnd(); for (QMap::ConstIterator it = m_textData.constBegin(); it != itEnd; ++it) if (it.value().isNull()) { txt.append(it.key().toLatin1()); } else { txt.append(it.key().toLatin1() + '=' + it.value()); } for (;;) { QDBusReply ret = m_group->AddService(-1, -1, 0, m_serviceName, m_type, domainToDNS(m_domain), m_hostName, m_port, txt); if (ret.isValid()) { break; } // serious error, bail out if (ret.error().name() != QLatin1String("org.freedesktop.Avahi.CollisionError")) { return false; } // name collision, try another QDBusReply rep = m_server->GetAlternativeServiceName(m_serviceName); if (rep.isValid()) { m_serviceName = rep.value(); } else { return false; } } for (const QString &subtype : qAsConst(m_subtypes)) { m_group->AddServiceSubtype(-1, -1, 0, m_serviceName, m_type, domainToDNS(m_domain), subtype); } return true; } void PublicServicePrivate::serverStateChanged(int s, const QString &) { if (!m_running) { return; } switch (s) { case AVAHI_SERVER_INVALID: m_parent->stop(); emit m_parent->published(false); break; case AVAHI_SERVER_REGISTERING: case AVAHI_SERVER_COLLISION: if (m_group) { m_group->Reset(); } m_collision = true; break; case AVAHI_SERVER_RUNNING: if (m_collision) { m_collision = false; tryApply(); } } } void PublicService::publishAsync() { K_D; if (d->m_running) { stop(); } if (!d->m_server) { d->m_server = new org::freedesktop::Avahi::Server(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus()); connect(d->m_server, SIGNAL(StateChanged(int,QString)), d, SLOT(serverStateChanged(int,QString))); } int state = AVAHI_SERVER_INVALID; QDBusReply rep = d->m_server->GetState(); if (rep.isValid()) { state = rep.value(); } d->m_running = true; d->m_collision = true; // make it look like server is getting out of collision to force registering d->serverStateChanged(state, QString()); } void PublicServicePrivate::groupStateChanged(int s, const QString &reason) { switch (s) { case AVAHI_ENTRY_GROUP_COLLISION: { QDBusReply rep = m_server->GetAlternativeServiceName(m_serviceName); if (rep.isValid()) { m_parent->setServiceName(rep.value()); } else { serverStateChanged(AVAHI_SERVER_INVALID, reason); } break; } case AVAHI_ENTRY_GROUP_ESTABLISHED: m_published = true; emit m_parent->published(true); break; case AVAHI_ENTRY_GROUP_FAILURE: serverStateChanged(AVAHI_SERVER_INVALID, reason); break; } } void PublicService::virtual_hook(int, void *) { } } #include "moc_publicservice.cpp" #include "moc_avahi-publicservice_p.cpp" diff --git a/src/avahi-publicservice_p.h b/src/avahi-publicservice_p.h index 190b6ee..0ea5155 100644 --- a/src/avahi-publicservice_p.h +++ b/src/avahi-publicservice_p.h @@ -1,83 +1,71 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef AVAHI_PUBLICSERVICE_P_H #define AVAHI_PUBLICSERVICE_P_H #include #include "servicebase_p.h" #include #include "publicservice.h" #include "avahi_listener_p.h" #include "avahi_server_interface.h" #include "avahi_entrygroup_interface.h" #define K_D PublicServicePrivate* d=static_cast(this->d) namespace KDNSSD { class PublicServicePrivate : public QObject, public ServiceBasePrivate, public AvahiListener { Q_OBJECT public: PublicServicePrivate(PublicService *parent, const QString &name, const QString &type, const QString &domain, unsigned int port) : QObject(), ServiceBasePrivate(name, type, domain, QString(), port), m_published(false), m_running(false), m_group(nullptr), m_server(nullptr), m_collision(false), m_parent(parent) {} ~PublicServicePrivate() { if (m_group) { m_group->Free(); } delete m_group; delete m_server; } bool m_published; bool m_running; org::freedesktop::Avahi::EntryGroup *m_group; org::freedesktop::Avahi::Server *m_server; bool m_collision; QStringList m_subtypes; PublicService *m_parent; void commit() { if (!m_collision) { m_group->Commit(); } } void stop(); bool fillEntryGroup(); void tryApply(); public Q_SLOTS: // NB: The global slots are runtime connected! If their signature changes // make sure the SLOT() signature gets updated! void gotGlobalStateChanged(int state, const QString &error, QDBusMessage msg); void serverStateChanged(int, const QString &); void groupStateChanged(int, const QString &); }; } #endif diff --git a/src/avahi-remoteservice.cpp b/src/avahi-remoteservice.cpp index f64a93f..262841b 100644 --- a/src/avahi-remoteservice.cpp +++ b/src/avahi-remoteservice.cpp @@ -1,190 +1,178 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004, 2005 Jakub Stachowski - * Copyright (C) 2018 Harald Sitter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004, 2005 Jakub Stachowski + SPDX-FileCopyrightText: 2018 Harald Sitter + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "avahi-remoteservice_p.h" #include #include #include #include #include "remoteservice.h" #include "avahi_server_interface.h" #include "avahi_serviceresolver_interface.h" namespace KDNSSD { RemoteService::RemoteService(const QString &name, const QString &type, const QString &domain) : ServiceBase(new RemoteServicePrivate(this, name, type, domain)) { } RemoteService::~RemoteService() { } bool RemoteService::resolve() { K_D; resolveAsync(); while (d->m_running && !d->m_resolved) { QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } return d->m_resolved; } void RemoteService::resolveAsync() { K_D; if (d->m_running) { return; } d->m_resolved = false; registerTypes(); // Do not race! // https://github.com/lathiat/avahi/issues/9 // Avahi's DBus API is incredibly racey with signals getting fired // immediately after a request was made even though we may not yet be // listening. In lieu of a proper upstream fix for this we'll unfortunately // have to resort to this hack: // We register to all signals regardless of path and then filter them once // we know what "our" path is. This is much more fragile than a proper // QDBusInterface assisted signal connection but unfortunately the only way // we can reliably prevent signals getting lost in the race. // This uses a fancy trick whereby using QDBusMessage as last argument will // give us the correct signal argument types as well as the underlying // message so that we may check the message path. QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.ServiceResolver", "Found", d, SLOT(gotGlobalFound(int,int,QString,QString,QString,QString, int,QString,ushort,QList, uint,QDBusMessage))); QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.ServiceResolver", "Failure", d, SLOT(gotGlobalError(QDBusMessage))); d->m_dbusObjectPath.clear(); //qDebug() << this << ":Starting resolve of : " << d->m_serviceName << " " << d->m_type << " " << d->m_domain << "\n"; org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus()); //FIXME: don't use LOOKUP_NO_ADDRESS if NSS unavailable QDBusReply rep = s.ServiceResolverNew(-1, -1, d->m_serviceName, d->m_type, domainToDNS(d->m_domain), -1, 8 /*AVAHI_LOOKUP_NO_ADDRESS*/); if (!rep.isValid()) { emit resolved(false); return; } d->m_dbusObjectPath = rep.value().path(); // This is held because we need to explicitly Free it! d->m_resolver = new org::freedesktop::Avahi::ServiceResolver( s.service(), d->m_dbusObjectPath, s.connection()); d->m_running = true; } bool RemoteService::isResolved() const { K_D; return d->m_resolved; } void RemoteServicePrivate::gotError() { m_resolved = false; stop(); emit m_parent->resolved(false); } void RemoteServicePrivate::gotGlobalFound(int interface, int protocol, const QString &name, const QString &type, const QString &domain, const QString &host, int aprotocol, const QString &address, ushort port, const QList &txt, uint flags, QDBusMessage msg) { if (!isOurMsg(msg)) { return; } gotFound(interface, protocol, name, type, domain, host, aprotocol, address, port, txt, flags); } void RemoteServicePrivate::gotGlobalError(QDBusMessage msg) { if (!isOurMsg(msg)) { return; } gotError(); } void RemoteServicePrivate::gotFound(int, int, const QString &name, const QString &, const QString &domain, const QString &host, int, const QString &, ushort port, const QList &txt, uint) { m_serviceName = name; m_hostName = host; m_port = port; m_domain = DNSToDomain(domain); for (const QByteArray &x : txt) { int pos = x.indexOf("="); if (pos == -1) { m_textData[x] = QByteArray(); } else { m_textData[x.mid(0, pos)] = x.mid(pos + 1, x.size() - pos); } } m_resolved = true; emit m_parent->resolved(true); } void RemoteServicePrivate::stop() { if (m_resolver) { m_resolver->Free(); } delete m_resolver; m_resolver = nullptr; m_running = false; } void RemoteService::virtual_hook(int, void *) { // BASE::virtual_hook(int, void*); } } #include "moc_remoteservice.cpp" #include "moc_avahi-remoteservice_p.cpp" diff --git a/src/avahi-remoteservice_p.h b/src/avahi-remoteservice_p.h index 877b08a..04828b4 100644 --- a/src/avahi-remoteservice_p.h +++ b/src/avahi-remoteservice_p.h @@ -1,91 +1,79 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef AVAHI_REMOTESERVICE_P_H #define AVAHI_REMOTESERVICE_P_H #include #include #include #include "servicebase_p.h" #include "remoteservice.h" #include "avahi_listener_p.h" #include "avahi_serviceresolver_interface.h" #define K_D RemoteServicePrivate* d=static_cast(this->d) namespace KDNSSD { class RemoteServicePrivate : public QObject, public ServiceBasePrivate, public AvahiListener { Q_OBJECT public: RemoteServicePrivate(RemoteService *parent, const QString &name, const QString &type, const QString &domain) : QObject(), ServiceBasePrivate(name, type, domain, QString(), 0), m_resolved(false), m_running(false), m_resolver(nullptr), m_parent(parent) {} ~RemoteServicePrivate() { if (m_resolver) { m_resolver->Free(); } delete m_resolver; } bool m_resolved = false; bool m_running = false; org::freedesktop::Avahi::ServiceResolver *m_resolver = nullptr; RemoteService *m_parent = nullptr; void stop(); private Q_SLOTS: // NB: The global slots are runtime connected! If their signature changes // make sure the SLOT() signature gets updated! void gotGlobalFound( int interface, int protocol, const QString &name, const QString &type, const QString &domain, const QString &host, int aprotocol, const QString &address, ushort port, const QList &txt, uint flags, QDBusMessage msg); void gotGlobalError(QDBusMessage msg); void gotFound( int interface, int protocol, const QString &name, const QString &type, const QString &domain, const QString &host, int aprotocol, const QString &address, ushort port, const QList &txt, uint flags); void gotError(); }; } #endif diff --git a/src/avahi-servicebrowser.cpp b/src/avahi-servicebrowser.cpp index 0439615..aed13fa 100644 --- a/src/avahi-servicebrowser.cpp +++ b/src/avahi-servicebrowser.cpp @@ -1,280 +1,268 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * Copyright (C) 2018 Harald Sitter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + SPDX-FileCopyrightText: 2018 Harald Sitter + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "avahi-servicebrowser_p.h" #include #include "servicebrowser.h" #include "avahi_servicebrowser_interface.h" #include "avahi_server_interface.h" #include #include namespace KDNSSD { ServiceBrowser::ServiceBrowser(const QString &type, bool autoResolve, const QString &domain, const QString &subtype) : d(new ServiceBrowserPrivate(this)) { d->m_type = type; d->m_subtype = subtype; d->m_autoResolve = autoResolve; d->m_domain = domain; d->m_timer.setSingleShot(true); } ServiceBrowser::State ServiceBrowser::isAvailable() { org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus()); QDBusReply rep = s.GetState(); return (rep.isValid() && rep.value() == 2) ? Working : Stopped; } ServiceBrowser::~ServiceBrowser() { delete d; } bool ServiceBrowser::isAutoResolving() const { return d->m_autoResolve; } void ServiceBrowser::startBrowse() { if (d->m_running) { return; } // Do not race! // https://github.com/lathiat/avahi/issues/9 // Avahi's DBus API is incredibly racey with signals getting fired // immediately after a request was made even though we may not yet be // listening. In lieu of a proper upstream fix for this we'll unfortunately // have to resort to this hack: // We register to all signals regardless of path and then filter them once // we know what "our" path is. This is much more fragile than a proper // QDBusInterface assisted signal connection but unfortunately the only way // we can reliably prevent signals getting lost in the race. // This uses a fancy trick whereby using QDBusMessage as last argument will // give us the correct signal argument types as well as the underlying // message so that we may check the message path. QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.ServiceBrowser", "ItemNew", d, SLOT(gotGlobalItemNew(int,int,QString,QString,QString,uint,QDBusMessage))); QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.ServiceBrowser", "ItemRemove", d, SLOT(gotGlobalItemRemove(int,int,QString,QString,QString,uint,QDBusMessage))); QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.ServiceBrowser", "AllForNow", d, SLOT(gotGlobalAllForNow(QDBusMessage))); d->m_dbusObjectPath.clear(); org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus()); QString fullType = d->m_type; if (!d->m_subtype.isEmpty()) { fullType = d->m_subtype + QStringLiteral("._sub.") + d->m_type; } QDBusReply rep = s.ServiceBrowserNew(-1, -1, fullType, domainToDNS(d->m_domain), 0); if (!rep.isValid()) { emit finished(); return; } d->m_dbusObjectPath = rep.value().path(); d->m_running = true; d->m_browserFinished = true; // This is held because we need to explicitly Free it! d->m_browser = new org::freedesktop::Avahi::ServiceBrowser( s.service(), d->m_dbusObjectPath, s.connection()); connect(&d->m_timer, &QTimer::timeout, d, &ServiceBrowserPrivate::browserFinished); d->m_timer.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAST_SERVICE : TIMEOUT_START_WAN); } void ServiceBrowserPrivate::serviceResolved(bool success) { QObject *sender_obj = const_cast(sender()); RemoteService *svr = static_cast(sender_obj); disconnect(svr, SIGNAL(resolved(bool)), this, SLOT(serviceResolved(bool))); QList::Iterator it = m_duringResolve.begin(); QList::Iterator itEnd = m_duringResolve.end(); while (it != itEnd && svr != (*it).data()) { ++it; } if (it != itEnd) { if (success) { m_services += (*it); emit m_parent->serviceAdded(RemoteService::Ptr(svr)); } m_duringResolve.erase(it); queryFinished(); } } void ServiceBrowserPrivate::gotGlobalItemNew(int interface, int protocol, const QString &name, const QString &type, const QString &domain, uint flags, QDBusMessage msg) { if (!isOurMsg(msg)) { return; } gotNewService(interface, protocol, name, type, domain, flags); } void ServiceBrowserPrivate::gotGlobalItemRemove(int interface, int protocol, const QString &name, const QString &type, const QString &domain, uint flags, QDBusMessage msg) { if (!isOurMsg(msg)) { return; } gotRemoveService(interface, protocol, name, type, domain, flags); } void ServiceBrowserPrivate::gotGlobalAllForNow(QDBusMessage msg) { if (!isOurMsg(msg)) { return; } browserFinished(); } RemoteService::Ptr ServiceBrowserPrivate::find(RemoteService::Ptr s, const QList &where) const { for (const RemoteService::Ptr &i : where) if (*s == *i) { return i; } return RemoteService::Ptr(); } void ServiceBrowserPrivate::gotNewService(int, int, const QString &name, const QString &type, const QString &domain, uint) { m_timer.start(TIMEOUT_LAST_SERVICE); RemoteService::Ptr svr(new RemoteService(name, type, domain)); if (m_autoResolve) { connect(svr.data(), SIGNAL(resolved(bool)), this, SLOT(serviceResolved(bool))); m_duringResolve += svr; svr->resolveAsync(); } else { m_services += svr; emit m_parent->serviceAdded(svr); } } void ServiceBrowserPrivate::gotRemoveService(int, int, const QString &name, const QString &type, const QString &domain, uint) { m_timer.start(TIMEOUT_LAST_SERVICE); RemoteService::Ptr tmpl(new RemoteService(name, type, domain)); RemoteService::Ptr found = find(tmpl, m_duringResolve); if (found) { m_duringResolve.removeAll(found); return; } found = find(tmpl, m_services); if (!found) { return; } emit m_parent->serviceRemoved(found); m_services.removeAll(found); } void ServiceBrowserPrivate::browserFinished() { m_timer.stop(); m_browserFinished = true; queryFinished(); } void ServiceBrowserPrivate::queryFinished() { if (!m_duringResolve.count() && m_browserFinished) { emit m_parent->finished(); } } QList ServiceBrowser::services() const { return d->m_services; } void ServiceBrowser::virtual_hook(int, void *) {} QHostAddress ServiceBrowser::resolveHostName(const QString &hostname) { org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus()); int protocol = 0; QString name; int aprotocol = 0; QString address; uint flags = 0; QDBusReply reply = s.ResolveHostName(-1, -1, hostname, 0, (unsigned int) 0, protocol, name, aprotocol, address, flags); if (reply.isValid()) { return QHostAddress(address); } else { return QHostAddress(); } } QString ServiceBrowser::getLocalHostName() { org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus()); QDBusReply reply = s.GetHostName(); if (reply.isValid()) { return reply.value(); } else { return QString(); } } } #include "moc_servicebrowser.cpp" #include "moc_avahi-servicebrowser_p.cpp" diff --git a/src/avahi-servicebrowser_p.h b/src/avahi-servicebrowser_p.h index e35d578..065b84f 100644 --- a/src/avahi-servicebrowser_p.h +++ b/src/avahi-servicebrowser_p.h @@ -1,92 +1,80 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef AVAHI_SERVICEBROWSER_P_H #define AVAHI_SERVICEBROWSER_P_H #include #include #include #include "servicebrowser.h" #include "avahi_listener_p.h" #include "avahi_servicebrowser_interface.h" namespace KDNSSD { class ServiceBrowserPrivate : public QObject, public AvahiListener { Q_OBJECT friend class ServiceBrowser; // So the public class may functor connect. public: ServiceBrowserPrivate(ServiceBrowser *parent) : QObject(), m_running(false), m_browser(nullptr), m_parent(parent) {} ~ServiceBrowserPrivate() { if (m_browser) { m_browser->Free(); } delete m_browser; } QList m_services; QList m_duringResolve; QString m_type; QString m_domain; QString m_subtype; bool m_autoResolve = false; bool m_running = false; bool m_finished = false; bool m_browserFinished = false; QTimer m_timer; org::freedesktop::Avahi::ServiceBrowser *m_browser = nullptr; ServiceBrowser *m_parent = nullptr; // get already found service identical to s or null if not found RemoteService::Ptr find(RemoteService::Ptr s, const QList &where) const; private Q_SLOTS: void browserFinished(); void queryFinished(); void serviceResolved(bool success); // NB: The global slots are runtime connected! If their signature changes // make sure the SLOT() signature gets updated! void gotGlobalItemNew(int interface, int protocol, const QString &name, const QString &type, const QString &domain, uint flags, QDBusMessage msg); void gotGlobalItemRemove(int interface, int protocol, const QString &name, const QString &type, const QString &domain, uint flags, QDBusMessage msg); void gotGlobalAllForNow(QDBusMessage msg); void gotNewService(int, int, const QString &, const QString &, const QString &, uint); void gotRemoveService(int, int, const QString &, const QString &, const QString &, uint); }; } #endif diff --git a/src/avahi-servicetypebrowser.cpp b/src/avahi-servicetypebrowser.cpp index 488fc4a..6cbc5a1 100644 --- a/src/avahi-servicetypebrowser.cpp +++ b/src/avahi-servicetypebrowser.cpp @@ -1,166 +1,154 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004,2007 Jakub Stachowski - * Copyright (C) 2018 Harald Sitter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004, 2007 Jakub Stachowski + SPDX-FileCopyrightText: 2018 Harald Sitter + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "avahi-servicetypebrowser_p.h" #include #include "avahi_server_interface.h" #include "servicetypebrowser.h" #include "avahi_servicetypebrowser_interface.h" #define UNSPEC -1 namespace KDNSSD { ServiceTypeBrowser::ServiceTypeBrowser(const QString &domain, QObject *parent) : QObject(parent), d(new ServiceTypeBrowserPrivate(this)) { d->m_domain = domain; d->m_timer.setSingleShot(true); } ServiceTypeBrowser::~ServiceTypeBrowser() { delete d; } void ServiceTypeBrowser::startBrowse() { if (d->m_started) { return; } d->m_started = true; // Do not race! // https://github.com/lathiat/avahi/issues/9 // Avahi's DBus API is incredibly racey with signals getting fired // immediately after a request was made even though we may not yet be // listening. In lieu of a proper upstream fix for this we'll unfortunately // have to resort to this hack: // We register to all signals regardless of path and then filter them once // we know what "our" path is. This is much more fragile than a proper // QDBusInterface assisted signal connection but unfortunately the only way // we can reliably prevent signals getting lost in the race. // This uses a fancy trick whereby using QDBusMessage as last argument will // give us the correct signal argument types as well as the underlying // message so that we may check the message path. QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.ServiceTypeBrowser", "ItemNew", d, SLOT(gotGlobalItemNew(int,int,QString,QString,uint,QDBusMessage))); QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.ServiceTypeBrowser", "ItemRemove", d, SLOT(gotGlobalItemRemove(int,int,QString,QString,uint,QDBusMessage))); QDBusConnection::systemBus() .connect("org.freedesktop.Avahi", "", "org.freedesktop.Avahi.ServiceTypeBrowser", "AllForNow", d, SLOT(gotGlobalAllForNow(QDBusMessage))); d->m_dbusObjectPath.clear(); org::freedesktop::Avahi::Server s(QStringLiteral("org.freedesktop.Avahi"), QStringLiteral("/"), QDBusConnection::systemBus()); QDBusReply rep = s.ServiceTypeBrowserNew(-1, -1, d->m_domain, 0); if (!rep.isValid()) { return; } d->m_dbusObjectPath = rep.value().path(); // This is held because we need to explicitly Free it! d->m_browser = new org::freedesktop::Avahi::ServiceTypeBrowser( s.service(), d->m_dbusObjectPath, s.connection()); connect(&d->m_timer, SIGNAL(timeout()), d, SLOT(finished())); d->m_timer.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAST_SERVICE : TIMEOUT_START_WAN); } void ServiceTypeBrowserPrivate::finished() { m_timer.stop(); emit m_parent->finished(); } void ServiceTypeBrowserPrivate::gotGlobalItemNew(int interface, int protocol, const QString &type, const QString &domain, uint flags, QDBusMessage msg) { if (!isOurMsg(msg)) { return; } gotNewServiceType(interface, protocol, type, domain, flags); } void ServiceTypeBrowserPrivate::gotGlobalItemRemove(int interface, int protocol, const QString &type, const QString &domain, uint flags, QDBusMessage msg) { if (!isOurMsg(msg)) { return; } gotRemoveServiceType(interface, protocol, type, domain, flags); } void ServiceTypeBrowserPrivate::gotGlobalAllForNow(QDBusMessage msg) { if (!isOurMsg(msg)) { return; } finished(); } void ServiceTypeBrowserPrivate::gotNewServiceType(int, int, const QString &type, const QString &, uint) { m_timer.start(TIMEOUT_LAST_SERVICE); m_servicetypes += type; emit m_parent->serviceTypeAdded(type); } void ServiceTypeBrowserPrivate::gotRemoveServiceType(int, int, const QString &type, const QString &, uint) { m_timer.start(TIMEOUT_LAST_SERVICE); m_servicetypes.removeAll(type); emit m_parent->serviceTypeRemoved(type); } QStringList ServiceTypeBrowser::serviceTypes() const { return d->m_servicetypes; } } #include "moc_servicetypebrowser.cpp" #include "moc_avahi-servicetypebrowser_p.cpp" diff --git a/src/avahi-servicetypebrowser_p.h b/src/avahi-servicetypebrowser_p.h index b9b4e55..1a7f33f 100644 --- a/src/avahi-servicetypebrowser_p.h +++ b/src/avahi-servicetypebrowser_p.h @@ -1,76 +1,64 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004,2007 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004,2007 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef AVAHI_SERVICETYPEBROWSER_P_H #define AVAHI_SERVICETYPEBROWSER_P_H #include #include #include "servicetypebrowser.h" #include "avahi_listener_p.h" #include "avahi_servicetypebrowser_interface.h" namespace KDNSSD { class ServiceTypeBrowserPrivate : public QObject, public AvahiListener { Q_OBJECT public: ServiceTypeBrowserPrivate(ServiceTypeBrowser *parent) : m_browser(nullptr), m_parent(parent), m_started(false) {} ~ServiceTypeBrowserPrivate() { if (m_browser) { m_browser->Free(); } } org::freedesktop::Avahi::ServiceTypeBrowser *m_browser = nullptr; ServiceTypeBrowser *m_parent = nullptr; bool m_started = false; QStringList m_servicetypes; QString m_domain; QTimer m_timer; private Q_SLOTS: // NB: The global slots are runtime connected! If their signature changes // make sure the SLOT() signature gets updated! void gotGlobalItemNew(int interface, int protocol, const QString &type, const QString &domain, uint flags, QDBusMessage msg); void gotGlobalItemRemove(int interface, int protocol, const QString &type, const QString &domain, uint flags, QDBusMessage msg); void gotGlobalAllForNow(QDBusMessage msg); void gotNewServiceType(int, int, const QString &, const QString &, uint); void gotRemoveServiceType(int, int, const QString &, const QString &, uint); void finished(); }; } #endif diff --git a/src/avahi_listener.cpp b/src/avahi_listener.cpp index 4c8fcd8..395a4f3 100644 --- a/src/avahi_listener.cpp +++ b/src/avahi_listener.cpp @@ -1,35 +1,23 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2018 Harald Sitter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2018 Harald Sitter + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "avahi_listener_p.h" namespace KDNSSD { AvahiListener::AvahiListener() { } AvahiListener::~AvahiListener() { } } // namespace KDNSSD diff --git a/src/avahi_listener_p.h b/src/avahi_listener_p.h index c3b1d0a..98d0460 100644 --- a/src/avahi_listener_p.h +++ b/src/avahi_listener_p.h @@ -1,54 +1,42 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2018 Harald Sitter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2018 Harald Sitter + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef AVAHILISTENER_H #define AVAHILISTENER_H #include #include namespace KDNSSD { // Assists with listening to Avahi for all signals and then checking if the // a given dbus message is meant for us or not. // Subclass and set the object path to object path you should be listening to. // Messages may then be run through isOurMsg to determine if they target the // object at hand. class AvahiListener { public: explicit AvahiListener(); virtual ~AvahiListener(); // This method gets called a lot but doesn't do much. Suggest inlining. inline bool isOurMsg(const QDBusMessage &msg) const { if (m_dbusObjectPath.isEmpty() || m_dbusObjectPath != msg.path()) { return false; } return true; } QString m_dbusObjectPath; // public so !Private objects can access it }; } // namespace KDNSSD #endif // AVAHILISTENER_H diff --git a/src/domainbrowser.h b/src/domainbrowser.h index 2805122..f1d308e 100644 --- a/src/domainbrowser.h +++ b/src/domainbrowser.h @@ -1,144 +1,132 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef KDNSSDDOMAINBROWSER_H #define KDNSSDDOMAINBROWSER_H #include #include class QStringList; namespace KDNSSD { class DomainBrowserPrivate; /** * @class DomainBrowser domainbrowser.h KDNSSD/DomainBrowser * @short Browses recommended domains for browsing or publishing to. * * Usage of this class is very simple. If you are interested in * browsing for services, simple do * @code * KDNSSD::DomainBrowser *browser = * new KDNSSD::DomainBrowser(KDNSSD::DomainBrowser::Browsing, this); * connect(browser, SIGNAL(domainAdded(QString)), * this, SLOT(browsingDomainAdded(QString)); * connect(browser, SIGNAL(domainRemoved(QString)), * this, SLOT(browsingDomainRemove(QString)); * browser->startBrowse(); * @endcode * * If you are interested in domains where you can register services, * usage is identical except that you should pass * KDNSSD::DomainBrowser::Registering to the constructor. * * @author Jakub Stachowski */ class KDNSSD_EXPORT DomainBrowser : public QObject { Q_OBJECT public: /** * A type of domain recommendation */ enum DomainType { /** Domains recommended for browsing for services on (using ServiceBrowser) */ Browsing, /** Domains recommended for publishing to (using PublicService) */ Publishing }; /** * Standard constructor * * The global DNS-SD configuration (for example, the global Avahi * configuration for the Avahi backend) will be used. * * @param type the type of domain to search for * @param parent parent object (see QObject documentation) * * @see startBrowse() and ServiceBrowser::isAvailable() */ explicit DomainBrowser(DomainType type, QObject *parent = nullptr); ~DomainBrowser(); /** * The current known list of domains of the requested DomainType * * @return a list of currently known domain names */ QStringList domains() const; /** * Starts browsing * * Only the first call to this function will have any effect. * * Browsing stops when the DomainBrowser object is destroyed. * * @warning The domainAdded() signal may be emitted before this * function returns. * * @see domainAdded() and domainRemoved() */ void startBrowse(); /** * Whether the browsing has been started * * @return @c true if startBrowse() has been called, @c false otherwise */ bool isRunning() const; Q_SIGNALS: /** * A domain has disappeared from the browsed list * * Emitted when domain has been removed from browsing list * or the publishing list (depending on which list was * requested in the constructor). * * @param domain the name of the domain * * @see domainAdded() */ void domainRemoved(const QString &domain); /** * A new domain has been discovered * * If the requested DomainType is Browsing, this will * also be emitted for the domains specified in the * global configuration. * * @param domain the name of the domain * * @see domainRemoved() */ void domainAdded(const QString &domain); private: friend class DomainBrowserPrivate; DomainBrowserPrivate *const d; }; } #endif diff --git a/src/domainmodel.cpp b/src/domainmodel.cpp index 42c8c99..5dacee7 100644 --- a/src/domainmodel.cpp +++ b/src/domainmodel.cpp @@ -1,99 +1,87 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2008 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2008 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "domainmodel.h" #include "domainbrowser.h" #include namespace KDNSSD { struct DomainModelPrivate { DomainBrowser *m_browser; }; DomainModel::DomainModel(DomainBrowser *browser, QObject *parent) : QAbstractItemModel(parent), d(new DomainModelPrivate) { d->m_browser = browser; browser->setParent(this); connect(browser, SIGNAL(domainAdded(QString)), this, SIGNAL(layoutChanged())); connect(browser, SIGNAL(domainRemoved(QString)), this, SIGNAL(layoutChanged())); browser->startBrowse(); } DomainModel::~DomainModel() { delete d; } int DomainModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return 1; } int DomainModel::rowCount(const QModelIndex &parent) const { return (parent.isValid()) ? 0 : d->m_browser->domains().size(); } QModelIndex DomainModel::parent(const QModelIndex &index) const { Q_UNUSED(index); return QModelIndex(); } QModelIndex DomainModel::index(int row, int column, const QModelIndex &parent) const { return hasIndex(row, column, parent) ? createIndex(row, column) : QModelIndex(); } bool DomainModel::hasIndex(int row, int column, const QModelIndex &parent) const { if (parent.isValid()) { return false; } if (column != 0) { return false; } if (row < 0 || row >= rowCount(parent)) { return false; } return true; } QVariant DomainModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (!hasIndex(index.row(), index.column(), index.parent())) { return QVariant(); } const QStringList domains = d->m_browser->domains(); if (role == Qt::DisplayRole) { return domains[index.row()]; } return QVariant(); } } diff --git a/src/domainmodel.h b/src/domainmodel.h index 6fc1966..857616f 100644 --- a/src/domainmodel.h +++ b/src/domainmodel.h @@ -1,96 +1,84 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2008 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2008 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef KDNSSDDOMAINMODEL_H #define KDNSSDDOMAINMODEL_H #include #include namespace KDNSSD { struct DomainModelPrivate; class DomainBrowser; /** * @class DomainModel domainmodel.h KDNSSD/DomainModel * @short Model for list of Zeroconf domains * * This class provides a Qt Model for DomainBrowser to allow easy * integration of domain discovery into a GUI. For example, to * provide a combo box listing available domains, you can do: * @code * KDNSSD::DomainModel *domainModel = new DomainModel( * new KDNSSD::DomainBrowser(KDNSSD::DomainBrowser::Browsing) * ); * QComboBox *domainCombo = new QComboBox(); * domainCombo->setModel(domainModel); * @endcode * * @since 4.1 * @author Jakub Stachowski */ class KDNSSD_EXPORT DomainModel : public QAbstractItemModel { Q_OBJECT public: /** * Creates a model for given domain browser and starts * browsing for domains. * * The model takes ownership of the browser, * so there is no need to delete it afterwards. * * You should @b not call DomainBrowser::startBrowse() on @p browser * before passing it to DomainModel. * * @param browser the domain browser that will provide the domains * to be listed by the model * @param parent the parent object (see QObject documentation) */ explicit DomainModel(DomainBrowser *browser, QObject *parent = nullptr); virtual ~DomainModel(); /** @reimp */ int columnCount(const QModelIndex &parent = QModelIndex()) const override; /** @reimp */ int rowCount(const QModelIndex &parent = QModelIndex()) const override; /** @reimp */ QModelIndex parent(const QModelIndex &index) const override; /** @reimp */ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; /** @reimp */ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; /** @reimp */ virtual bool hasIndex(int row, int column, const QModelIndex &parent) const; private: DomainModelPrivate *const d; friend struct DomainModelPrivate; }; } #endif diff --git a/src/dummy-domainbrowser.cpp b/src/dummy-domainbrowser.cpp index 42c6363..24f5207 100644 --- a/src/dummy-domainbrowser.cpp +++ b/src/dummy-domainbrowser.cpp @@ -1,47 +1,35 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include #include "domainbrowser.h" namespace KDNSSD { DomainBrowser::DomainBrowser(DomainType, QObject *parent) : QObject(parent), d(nullptr) {} DomainBrowser::~DomainBrowser() {} void DomainBrowser::startBrowse() {} QStringList DomainBrowser::domains() const { return QStringList(); } bool DomainBrowser::isRunning() const { return false; } } #include "moc_domainbrowser.cpp" diff --git a/src/dummy-publicservice.cpp b/src/dummy-publicservice.cpp index 1c4aafc..59b33d7 100644 --- a/src/dummy-publicservice.cpp +++ b/src/dummy-publicservice.cpp @@ -1,99 +1,87 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004, 2005 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004, 2005 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "publicservice.h" #include "servicebase_p.h" #include namespace KDNSSD { PublicService::PublicService(const QString &name, const QString &type, unsigned int port, const QString &domain, const QStringList &) : QObject(), ServiceBase(name, type, QString(), domain, port) { if (domain.isNull()) { d->m_domain = QLatin1String("local."); } } PublicService::~PublicService() {} void PublicService::setServiceName(const QString &serviceName) { d->m_serviceName = serviceName; } void PublicService::setDomain(const QString &domain) { d->m_domain = domain; } void PublicService::setTextData(const QMap &textData) { d->m_textData = textData; } void PublicService::setType(const QString &type) { d->m_type = type; } void PublicService::setSubTypes(const QStringList &) { // dummy and empty } void PublicService::setPort(unsigned short port) { d->m_port = port; } QStringList PublicService::subtypes() const { return QStringList(); } bool PublicService::isPublished() const { return false; } bool PublicService::publish() { return false; } void PublicService::stop() {} void PublicService::publishAsync() { emit published(false); } void PublicService::virtual_hook(int, void *) { } } #include "moc_publicservice.cpp" diff --git a/src/dummy-remoteservice.cpp b/src/dummy-remoteservice.cpp index 41e1442..6b63cdb 100644 --- a/src/dummy-remoteservice.cpp +++ b/src/dummy-remoteservice.cpp @@ -1,58 +1,46 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004, 2005 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004, 2005 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "remoteservice.h" #include namespace KDNSSD { RemoteService::RemoteService(const QString &name, const QString &type, const QString &domain) : ServiceBase(name, type, domain) { } RemoteService::~RemoteService() { } bool RemoteService::resolve() { return false; } void RemoteService::resolveAsync() { emit resolved(false); } bool RemoteService::isResolved() const { return false; } void RemoteService::virtual_hook(int, void *) { // BASE::virtual_hook(int, void*); } } #include "moc_remoteservice.cpp" diff --git a/src/dummy-servicebrowser.cpp b/src/dummy-servicebrowser.cpp index 480cc01..2450020 100644 --- a/src/dummy-servicebrowser.cpp +++ b/src/dummy-servicebrowser.cpp @@ -1,71 +1,59 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include #include "domainbrowser.h" #include "servicebrowser.h" #include namespace KDNSSD { ServiceBrowser::ServiceBrowser(const QString &, bool, const QString &, const QString &) : d(nullptr) {} bool ServiceBrowser::isAutoResolving() const { return false; } ServiceBrowser::State ServiceBrowser::isAvailable() { return Unsupported; } ServiceBrowser::~ ServiceBrowser() { } void ServiceBrowser::startBrowse() { emit finished(); } QList ServiceBrowser::services() const { return QList(); } void ServiceBrowser::virtual_hook(int, void *) {} QHostAddress ServiceBrowser::resolveHostName(const QString &hostname) { Q_UNUSED(hostname); return QHostAddress(); } QString ServiceBrowser::getLocalHostName() { return QString(); } } #include "moc_servicebrowser.cpp" diff --git a/src/dummy-servicetypebrowser.cpp b/src/dummy-servicetypebrowser.cpp index db31219..ab893ac 100644 --- a/src/dummy-servicetypebrowser.cpp +++ b/src/dummy-servicetypebrowser.cpp @@ -1,42 +1,30 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include #include "servicetypebrowser.h" namespace KDNSSD { ServiceTypeBrowser::ServiceTypeBrowser(const QString &, QObject *parent) : QObject(parent), d(nullptr) {} ServiceTypeBrowser::~ServiceTypeBrowser() {} void ServiceTypeBrowser::startBrowse() {} QStringList ServiceTypeBrowser::serviceTypes() const { return QStringList(); } } #include "moc_servicetypebrowser.cpp" diff --git a/src/mdnsd-domainbrowser.cpp b/src/mdnsd-domainbrowser.cpp index 46966e7..72d7356 100644 --- a/src/mdnsd-domainbrowser.cpp +++ b/src/mdnsd-domainbrowser.cpp @@ -1,108 +1,96 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "mdnsd-domainbrowser_p.h" #include "domainbrowser.h" #include "remoteservice.h" #include "mdnsd-responder.h" #include "mdnsd-sdevent.h" #include #include #include namespace KDNSSD { void domain_callback(DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, const char *replyDomain, void *context); DomainBrowser::DomainBrowser(DomainType type, QObject *parent) : QObject(parent), d(new DomainBrowserPrivate(type, this)) { } DomainBrowser::~DomainBrowser() { delete d; } void DomainBrowser::startBrowse() { if (d->isRunning()) { return; } DNSServiceRef ref; if (DNSServiceEnumerateDomains(&ref, (d->m_type == Browsing) ? kDNSServiceFlagsBrowseDomains : kDNSServiceFlagsBrowseDomains, 0, domain_callback, reinterpret_cast(d)) == kDNSServiceErr_NoError) { d->setRef(ref); } } void DomainBrowserPrivate::customEvent(QEvent *event) { if (event->type() == QEvent::User + SD_ERROR) { stop(); } if (event->type() == QEvent::User + SD_ADDREMOVE) { AddRemoveEvent *aev = static_cast(event); if (aev->m_op == AddRemoveEvent::Add) { //FIXME: check if domain name is not name+domain (there was some mdnsd weirdness) if (m_domains.contains(aev->m_domain)) { return; } m_domains.append(aev->m_domain); emit m_parent->domainAdded(aev->m_domain); } else { m_domains.removeAll(aev->m_domain); emit m_parent->domainRemoved(aev->m_domain); } } } QStringList DomainBrowser::domains() const { return d->m_domains; } bool DomainBrowser::isRunning() const { return d->isRunning(); } void domain_callback(DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, const char *replyDomain, void *context) { QObject *obj = reinterpret_cast(context); if (errorCode != kDNSServiceErr_NoError) { ErrorEvent err; QCoreApplication::sendEvent(obj, &err); } else { // domain browser is supposed to return only _additional_ domains if (flags & kDNSServiceFlagsDefault) { return; } AddRemoveEvent arev((flags & kDNSServiceFlagsAdd) ? AddRemoveEvent::Add : AddRemoveEvent::Remove, QString(), QString(), DNSToDomain(replyDomain), !(flags & kDNSServiceFlagsMoreComing)); QCoreApplication::sendEvent(obj, &arev); } } } #include "moc_domainbrowser.cpp" diff --git a/src/mdnsd-domainbrowser_p.h b/src/mdnsd-domainbrowser_p.h index 7ea88bb..38e32ce 100644 --- a/src/mdnsd-domainbrowser_p.h +++ b/src/mdnsd-domainbrowser_p.h @@ -1,43 +1,31 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef MDNSD_DOMAINBROWSER_P_H #define MDNSD_DOMAINBROWSER_P_H #include "mdnsd-responder.h" #include "domainbrowser.h" #include namespace KDNSSD { class DomainBrowserPrivate : public Responder { Q_OBJECT public: DomainBrowserPrivate(DomainBrowser::DomainType type, DomainBrowser *parent): Responder(), m_type(type), m_parent(parent) {} DomainBrowser::DomainType m_type; DomainBrowser *m_parent = nullptr; QStringList m_domains; virtual void customEvent(QEvent *event); }; } #endif diff --git a/src/mdnsd-publicservice.cpp b/src/mdnsd-publicservice.cpp index 570b3c5..d393186 100644 --- a/src/mdnsd-publicservice.cpp +++ b/src/mdnsd-publicservice.cpp @@ -1,217 +1,205 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004, 2005 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004, 2005 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include #include #include #include "publicservice.h" #include "servicebase_p.h" #include "mdnsd-sdevent.h" #include "mdnsd-responder.h" #define K_D PublicServicePrivate* d=static_cast(this->d) namespace KDNSSD { void publish_callback(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *, const char *, void *context); class PublicServicePrivate : public Responder, public ServiceBasePrivate { public: PublicServicePrivate(PublicService *parent, const QString &name, const QString &type, unsigned int port, const QString &domain) : Responder(), ServiceBasePrivate(name, type, domain, QString(), port), m_published(false), m_parent(parent) {} bool m_published; PublicService *m_parent; QStringList m_subtypes; virtual void customEvent(QEvent *event); }; PublicService::PublicService(const QString &name, const QString &type, unsigned int port, const QString &domain, const QStringList &subtypes) : QObject(), ServiceBase(new PublicServicePrivate(this, name, type, port, domain)) { K_D; if (domain.isNull()) { d->m_domain = "local."; } d->m_subtypes = subtypes; } PublicService::~PublicService() { stop(); } void PublicService::setServiceName(const QString &serviceName) { K_D; d->m_serviceName = serviceName; if (d->isRunning()) { stop(); publishAsync(); } } void PublicService::setDomain(const QString &domain) { K_D; d->m_domain = domain; if (d->isRunning()) { stop(); publishAsync(); } } QStringList PublicService::subtypes() const { K_D; return d->m_subtypes; } void PublicService::setType(const QString &type) { K_D; d->m_type = type; if (d->isRunning()) { stop(); publishAsync(); } } void PublicService::setSubTypes(const QStringList &subtypes) { K_D; d->m_subtypes = subtypes; if (d->isRunning()) { stop(); publishAsync(); } } void PublicService::setPort(unsigned short port) { K_D; d->m_port = port; if (d->isRunning()) { stop(); publishAsync(); } } bool PublicService::isPublished() const { K_D; return d->m_published; } void PublicService::setTextData(const QMap &textData) { K_D; d->m_textData = textData; if (d->isRunning()) { stop(); publishAsync(); } } bool PublicService::publish() { K_D; publishAsync(); while (d->isRunning() && !d->m_published) { d->process(); } return d->m_published; } void PublicService::stop() { K_D; d->stop(); d->m_published = false; } void PublicService::publishAsync() { K_D; if (d->isRunning()) { stop(); } TXTRecordRef txt; TXTRecordCreate(&txt, 0, 0); QMap::ConstIterator itEnd = d->m_textData.cend(); for (QMap::ConstIterator it = d->m_textData.cbegin(); it != itEnd; ++it) { if (TXTRecordSetValue(&txt, it.key().toUtf8().constData(), it.value().length(), it.value().constData()) != kDNSServiceErr_NoError) { TXTRecordDeallocate(&txt); emit published(false); return; } } DNSServiceRef ref; QString fullType = d->m_type; for (const QString &subtype : qAsConst(d->m_subtypes)) { fullType += ',' + subtype; } if (DNSServiceRegister(&ref, 0, 0, d->m_serviceName.toUtf8().constData(), fullType.toLatin1().constData(), domainToDNS(d->m_domain).constData(), NULL, htons(d->m_port), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), publish_callback, reinterpret_cast(d)) == kDNSServiceErr_NoError) { d->setRef(ref); } TXTRecordDeallocate(&txt); if (!d->isRunning()) { emit published(false); } } void publish_callback(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *, const char *, void *context) { QObject *obj = reinterpret_cast(context); if (errorCode != kDNSServiceErr_NoError) { ErrorEvent err; QCoreApplication::sendEvent(obj, &err); } else { PublishEvent pev(QString::fromUtf8(name)); QCoreApplication::sendEvent(obj, &pev); } } void PublicServicePrivate::customEvent(QEvent *event) { if (event->type() == QEvent::User + SD_ERROR) { m_parent->stop(); emit m_parent->published(false); } if (event->type() == QEvent::User + SD_PUBLISH) { m_published = true; emit m_parent->published(true); m_serviceName = static_cast(event)->m_name; } } void PublicService::virtual_hook(int, void *) { } } #include "moc_publicservice.cpp" diff --git a/src/mdnsd-remoteservice.cpp b/src/mdnsd-remoteservice.cpp index 41b3161..d56a1e2 100644 --- a/src/mdnsd-remoteservice.cpp +++ b/src/mdnsd-remoteservice.cpp @@ -1,161 +1,149 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004, 2005 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004, 2005 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include #include #include #include #include "remoteservice.h" #include "servicebase_p.h" #include "mdnsd-responder.h" #include "mdnsd-sdevent.h" namespace KDNSSD { void resolve_callback(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char *, const char *hosttarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context ); #define K_D RemoteServicePrivate* d=static_cast(this->d) class RemoteServicePrivate : public Responder, public ServiceBasePrivate { public: RemoteServicePrivate(RemoteService *parent, const QString &name, const QString &type, const QString &domain) : Responder(), ServiceBasePrivate(name, type, domain, QString(), 0), m_resolved(false), m_parent(parent) {} bool m_resolved; RemoteService *m_parent; virtual void customEvent(QEvent *event); }; RemoteService::RemoteService(const QString &name, const QString &type, const QString &domain) : ServiceBase(new RemoteServicePrivate(this, name, type, domain)) { } RemoteService::~RemoteService() {} bool RemoteService::resolve() { K_D; resolveAsync(); while (d->isRunning() && !d->m_resolved) { d->process(); } d->stop(); return d->m_resolved; } void RemoteService::resolveAsync() { K_D; if (d->isRunning()) { return; } d->m_resolved = false; //qDebug() << this << ":Starting resolve of : " << d->m_serviceName << " " << d->m_type << " " << d->m_domain << "\n"; DNSServiceRef ref; if (DNSServiceResolve(&ref, 0, 0, d->m_serviceName.toUtf8().constData(), d->m_type.toLatin1().constData(), domainToDNS(d->m_domain).constData(), (DNSServiceResolveReply)resolve_callback, reinterpret_cast(d)) == kDNSServiceErr_NoError) { d->setRef(ref); } if (!d->isRunning()) { emit resolved(false); } } bool RemoteService::isResolved() const { K_D; return d->m_resolved; } void RemoteServicePrivate::customEvent(QEvent *event) { if (event->type() == QEvent::User + SD_ERROR) { stop(); m_resolved = false; emit m_parent->resolved(false); } if (event->type() == QEvent::User + SD_RESOLVE) { ResolveEvent *rev = static_cast(event); m_hostName = rev->m_hostname; m_port = rev->m_port; m_textData = rev->m_txtdata; m_resolved = true; emit m_parent->resolved(true); } } void RemoteService::virtual_hook(int, void *) { // BASE::virtual_hook(int, void*); } void resolve_callback(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char *, const char *hosttarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context ) { QObject *obj = reinterpret_cast(context); if (errorCode != kDNSServiceErr_NoError) { ErrorEvent err; QCoreApplication::sendEvent(obj, &err); return; } char key[256]; int index = 0; unsigned char valueLen; //qDebug() << "Resolve callback\n"; QMap map; const void *voidValue = 0; while (TXTRecordGetItemAtIndex(txtLen, txtRecord, index++, 256, key, &valueLen, &voidValue) == kDNSServiceErr_NoError) { if (voidValue) { map[QString::fromUtf8(key)] = QByteArray((const char *)voidValue, valueLen); } else { map[QString::fromUtf8(key)].clear(); } } ResolveEvent rev(DNSToDomain(hosttarget), ntohs(port), map); QCoreApplication::sendEvent(obj, &rev); } } #include "moc_remoteservice.cpp" diff --git a/src/mdnsd-responder.cpp b/src/mdnsd-responder.cpp index 586d27c..85c87b4 100644 --- a/src/mdnsd-responder.cpp +++ b/src/mdnsd-responder.cpp @@ -1,99 +1,87 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "mdnsd-responder.h" #include "servicebase.h" #include #include namespace KDNSSD { Responder::Responder(DNSServiceRef ref, QObject *parent) : QObject(parent), m_ref(0), m_socket(0) { setRef(ref); } void Responder::setRef(DNSServiceRef ref) { if (m_socket || m_ref) { stop(); } m_running = false; m_ref = ref; if (m_ref == 0) { return; } int fd = DNSServiceRefSockFD(ref); if (fd == -1) { return; } m_socket = new QSocketNotifier(fd, QSocketNotifier::Read, this); connect(m_socket, SIGNAL(activated(int)), this, SLOT(process())); m_running = true; } Responder::~Responder() { stop(); } void Responder::stop() { delete m_socket; m_socket = 0; if (m_ref) { DNSServiceRefDeallocate(m_ref); } m_ref = 0; m_running = false; } void Responder::process() { if (DNSServiceProcessResult(m_ref) != kDNSServiceErr_NoError) { stop(); } } bool Responder::isRunning() const { return m_running; } QByteArray domainToDNS(const QString &domain) { if (domainIsLocal(domain)) { return domain.toUtf8(); } else { return QUrl::toAce(domain); } } QString DNSToDomain(const char *domain) { if (domainIsLocal(domain)) { return QString::fromUtf8(domain); } else { return QUrl::fromAce(domain); } } } diff --git a/src/mdnsd-responder.h b/src/mdnsd-responder.h index 5576da2..aadf0e5 100644 --- a/src/mdnsd-responder.h +++ b/src/mdnsd-responder.h @@ -1,69 +1,57 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef MDNSD_RESPONDER_H #define MDNSD_RESPONDER_H #include #include #include namespace KDNSSD { /** This class should not be used directly. @author Jakub Stachowski @short Internal class wrapping dns_sd.h interface */ class Responder : public QObject { Q_OBJECT public: explicit Responder(DNSServiceRef ref = 0, QObject *parent = nullptr); ~Responder(); /** Returns true if it is possible to use mDNS service publishing and discovery. It needs mDNSResponder running. */ bool isRunning() const; void setRef(DNSServiceRef ref); void stop(); public Q_SLOTS: void process(); protected: DNSServiceRef m_ref; bool m_running; QSocketNotifier *m_socket; }; /* Utils functions */ // Encodes domain name using utf8() or IDN QByteArray domainToDNS(const QString &domain); QString DNSToDomain(const char *domain); } #endif diff --git a/src/mdnsd-sdevent.h b/src/mdnsd-sdevent.h index 1bf9fd5..0c1f796 100644 --- a/src/mdnsd-sdevent.h +++ b/src/mdnsd-sdevent.h @@ -1,80 +1,68 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef MDNSD_SDEVENT_H #define MDNSD_SDEVENT_H #include #include #include namespace KDNSSD { enum Operation { SD_ERROR = 101, SD_ADDREMOVE, SD_PUBLISH, SD_RESOLVE}; class ErrorEvent : public QEvent { public: ErrorEvent() : QEvent((QEvent::Type)(QEvent::User + SD_ERROR)) {} }; class AddRemoveEvent : public QEvent { public: enum Operation { Add, Remove }; AddRemoveEvent(Operation op, const QString &name, const QString &type, const QString &domain, bool last) : QEvent((QEvent::Type)(QEvent::User + SD_ADDREMOVE)), m_op(op), m_name(name), m_type(type), m_domain(domain), m_last(last) {} const Operation m_op; const QString m_name; const QString m_type; const QString m_domain; const bool m_last; }; class PublishEvent : public QEvent { public: PublishEvent(const QString &name) : QEvent((QEvent::Type)(QEvent::User + SD_PUBLISH)), m_name(name) {} const QString m_name; }; class ResolveEvent : public QEvent { public: ResolveEvent(const QString &hostname, unsigned short port, const QMap &txtdata) : QEvent((QEvent::Type)(QEvent::User + SD_RESOLVE)), m_hostname(hostname), m_port(port), m_txtdata(txtdata) {} const QString m_hostname; const unsigned short m_port; const QMap m_txtdata; }; } #endif diff --git a/src/mdnsd-servicebrowser.cpp b/src/mdnsd-servicebrowser.cpp index e5ada24..8575379 100644 --- a/src/mdnsd-servicebrowser.cpp +++ b/src/mdnsd-servicebrowser.cpp @@ -1,212 +1,200 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "mdnsd-servicebrowser_p.h" #include "domainbrowser.h" #include "servicebrowser.h" #include "mdnsd-responder.h" #include "remoteservice.h" #include "mdnsd-sdevent.h" #include #include #include #include #include #include #define TIMEOUT_WAN 2000 #define TIMEOUT_LAN 200 namespace KDNSSD { void query_callback(DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context); ServiceBrowser::ServiceBrowser(const QString &type, bool autoResolve, const QString &domain, const QString &subtype) : d(new ServiceBrowserPrivate(this)) { d->m_type = type; d->m_autoResolve = autoResolve; d->m_domain = domain; d->m_subtype = subtype; d->timeout.setSingleShot(true); connect(&d->timeout, SIGNAL(timeout()), d, SLOT(onTimeout())); } ServiceBrowser::State ServiceBrowser::isAvailable() { // DNSServiceRef ref; // bool ok (DNSServiceCreateConnection(&ref)==kDNSServiceErr_NoError); // if (ok) DNSServiceRefDeallocate(ref); // return (ok) ? Working : Stopped; return Working; } ServiceBrowser::~ ServiceBrowser() { delete d; } bool ServiceBrowser::isAutoResolving() const { return d->m_autoResolve; } void ServiceBrowserPrivate::serviceResolved(bool success) { QObject *sender_obj = const_cast(sender()); RemoteService *svr = static_cast(sender_obj); disconnect(svr, SIGNAL(resolved(bool)), this, SLOT(serviceResolved(bool))); QList::Iterator it = m_duringResolve.begin(); QList::Iterator itEnd = m_duringResolve.end(); while (it != itEnd && svr != (*it).data()) { ++it; } if (it != itEnd) { if (success) { m_services += (*it); emit m_parent->serviceAdded(RemoteService::Ptr(svr)); } m_duringResolve.erase(it); queryFinished(); } } void ServiceBrowser::startBrowse() { if (d->isRunning()) { return; } d->m_finished = false; DNSServiceRef ref; QString fullType = d->m_type; if (!d->m_subtype.isEmpty()) { fullType = d->m_subtype + "._sub." + d->m_type; } if (DNSServiceBrowse(&ref, 0, 0, fullType.toLatin1().constData(), domainToDNS(d->m_domain).constData(), query_callback, reinterpret_cast(d)) == kDNSServiceErr_NoError) { d->setRef(ref); } if (!d->isRunning()) { emit finished(); } else { d->timeout.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAN : TIMEOUT_WAN); } } void ServiceBrowserPrivate::queryFinished() { if (!m_duringResolve.count() && m_finished) { emit m_parent->finished(); } } QList ServiceBrowser::services() const { return d->m_services; } void ServiceBrowser::virtual_hook(int, void *) {} RemoteService::Ptr ServiceBrowserPrivate::find(RemoteService::Ptr s, const QList &where) const { for (const RemoteService::Ptr &i : where) if (*s == *i) { return i; } return RemoteService::Ptr(); } void ServiceBrowserPrivate::customEvent(QEvent *event) { if (event->type() == QEvent::User + SD_ERROR) { stop(); m_finished = false; queryFinished(); } if (event->type() == QEvent::User + SD_ADDREMOVE) { AddRemoveEvent *aev = static_cast(event); // m_type has useless trailing dot RemoteService::Ptr svr(new RemoteService(aev->m_name, aev->m_type.left(aev->m_type.length() - 1), aev->m_domain)); if (aev->m_op == AddRemoveEvent::Add) { if (m_autoResolve) { connect(svr.data(), SIGNAL(resolved(bool)), this, SLOT(serviceResolved(bool))); m_duringResolve += svr; svr->resolveAsync(); } else { m_services += svr; emit m_parent->serviceAdded(svr); } } else { RemoteService::Ptr found = find(svr, m_duringResolve); if (found) { m_duringResolve.removeAll(found); } else { found = find(svr, m_services); if (found) { emit m_parent->serviceRemoved(found); m_services.removeAll(found); } } } m_finished = aev->m_last; if (m_finished) { queryFinished(); } } } void ServiceBrowserPrivate::onTimeout() { m_finished = true; queryFinished(); } void query_callback(DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) { QObject *obj = reinterpret_cast(context); if (errorCode != kDNSServiceErr_NoError) { ErrorEvent err; QCoreApplication::sendEvent(obj, &err); } else { AddRemoveEvent arev((flags & kDNSServiceFlagsAdd) ? AddRemoveEvent::Add : AddRemoveEvent::Remove, QString::fromUtf8(serviceName), regtype, DNSToDomain(replyDomain), !(flags & kDNSServiceFlagsMoreComing)); QCoreApplication::sendEvent(obj, &arev); } } // TODO: Please Implement Me - Using a KResolver (if not natively) QHostAddress ServiceBrowser::resolveHostName(const QString &hostname) { return QHostAddress(); } QString ServiceBrowser::getLocalHostName() { return QHostInfo::localHostName(); } } #include "moc_servicebrowser.cpp" diff --git a/src/mdnsd-servicebrowser_p.h b/src/mdnsd-servicebrowser_p.h index f0fb716..5b564fa 100644 --- a/src/mdnsd-servicebrowser_p.h +++ b/src/mdnsd-servicebrowser_p.h @@ -1,60 +1,48 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef MDNSD_SERVICEBROWSER_P_H #define MDNSD_SERVICEBROWSER_P_H #include #include #include "mdnsd-responder.h" #include "servicebrowser.h" namespace KDNSSD { class ServiceBrowserPrivate : public Responder { Q_OBJECT public: ServiceBrowserPrivate(ServiceBrowser *parent) : Responder(), m_parent(parent) {} QList m_services; QList m_duringResolve; QString m_type; QString m_domain; QString m_subtype; bool m_autoResolve; bool m_finished; ServiceBrowser *m_parent; QTimer timeout; // get already found service identical to s or null if not found RemoteService::Ptr find(RemoteService::Ptr s, const QList &where) const; virtual void customEvent(QEvent *event); public Q_SLOTS: void queryFinished(); void serviceResolved(bool success); void onTimeout(); }; } #endif diff --git a/src/mdnsd-servicetypebrowser.cpp b/src/mdnsd-servicetypebrowser.cpp index cc1016f..ef5b3da 100644 --- a/src/mdnsd-servicetypebrowser.cpp +++ b/src/mdnsd-servicetypebrowser.cpp @@ -1,67 +1,55 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "mdnsd-servicetypebrowser_p.h" #include "servicetypebrowser.h" #include "servicebrowser.h" namespace KDNSSD { ServiceTypeBrowser::ServiceTypeBrowser(const QString &domain, QObject *parent) : QObject(parent), d(new ServiceTypeBrowserPrivate(this)) { d->m_browser = new ServiceBrowser("_services._dns-sd._udp", false, domain); connect(d->m_browser, SIGNAL(serviceAdded(KDNSSD::RemoteService::Ptr)), d, SLOT(newService(KDNSSD::RemoteService::Ptr))); connect(d->m_browser, SIGNAL(serviceRemoved(KDNSSD::RemoteService::Ptr)), d, SLOT(removeService(KDNSSD::RemoteService::Ptr))); connect(d->m_browser, SIGNAL(finished()), this, SIGNAL(finished())); } ServiceTypeBrowser::~ServiceTypeBrowser() { delete d; } QStringList ServiceTypeBrowser::serviceTypes() const { return d->m_servicetypes; } void ServiceTypeBrowser::startBrowse() { d->m_browser->startBrowse(); } void ServiceTypeBrowserPrivate::newService(KDNSSD::RemoteService::Ptr srv) { QString type = srv->serviceName() + '.' + srv->type(); m_servicetypes += type; emit m_parent->serviceTypeAdded(type); } void ServiceTypeBrowserPrivate::removeService(KDNSSD::RemoteService::Ptr srv) { QString type = srv->serviceName() + '.' + srv->type(); m_servicetypes.removeAll(type); emit m_parent->serviceTypeRemoved(type); } } #include "moc_servicetypebrowser.cpp" diff --git a/src/mdnsd-servicetypebrowser_p.h b/src/mdnsd-servicetypebrowser_p.h index 124aa03..28302ef 100644 --- a/src/mdnsd-servicetypebrowser_p.h +++ b/src/mdnsd-servicetypebrowser_p.h @@ -1,46 +1,34 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef MDNSD_SERVICETYPEBROWSER_P_H #define MDNSD_SERVICETYPEBROWSER_P_H #include #include "servicebrowser.h" #include "servicetypebrowser.h" namespace KDNSSD { class ServiceTypeBrowserPrivate : public QObject { Q_OBJECT public: explicit ServiceTypeBrowserPrivate(ServiceTypeBrowser *parent): m_parent(parent) {} ServiceTypeBrowser *m_parent = nullptr; ServiceBrowser *m_browser = nullptr; QStringList m_servicetypes; public Q_SLOTS: void newService(KDNSSD::RemoteService::Ptr); void removeService(KDNSSD::RemoteService::Ptr); }; } #endif diff --git a/src/org.freedesktop.Avahi.DomainBrowser.xml b/src/org.freedesktop.Avahi.DomainBrowser.xml index 9f64db9..fd0fd39 100644 --- a/src/org.freedesktop.Avahi.DomainBrowser.xml +++ b/src/org.freedesktop.Avahi.DomainBrowser.xml @@ -1,56 +1,43 @@ - + - + - + diff --git a/src/org.freedesktop.Avahi.ServiceBrowser.xml b/src/org.freedesktop.Avahi.ServiceBrowser.xml index d2db359..10b7f9a 100644 --- a/src/org.freedesktop.Avahi.ServiceBrowser.xml +++ b/src/org.freedesktop.Avahi.ServiceBrowser.xml @@ -1,59 +1,46 @@ - + - + - + diff --git a/src/org.freedesktop.Avahi.ServiceTypeBrowser.xml b/src/org.freedesktop.Avahi.ServiceTypeBrowser.xml index 0468168..37d3b28 100644 --- a/src/org.freedesktop.Avahi.ServiceTypeBrowser.xml +++ b/src/org.freedesktop.Avahi.ServiceTypeBrowser.xml @@ -1,57 +1,44 @@ - + - + - + diff --git a/src/publicservice.h b/src/publicservice.h index 481546b..df89b84 100644 --- a/src/publicservice.h +++ b/src/publicservice.h @@ -1,235 +1,223 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004, 2005 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004, 2005 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef KDNSSDPUBLICSERVICE_H #define KDNSSDPUBLICSERVICE_H #include #include #include namespace KDNSSD { class PublicServicePrivate; /** * @class PublicService publicservice.h KDNSSD/PublicService * @short Represents a service to be published * * This class allows you to publish the existence of a network * service provided by your application. * * If you are providing a web server and want to advertise it * on the local network, you might do * @code * KDNSSD::PublicService *service = new KDNSSD::PublicService("My files", "_http._tcp", 80); * bool isOK = service->publish(); * @endcode * * In this example publish() is synchronous: it will not return * until publishing is complete. This is usually not too long * but it can freeze an application's GUI for a moment. * To publish asynchronously instead, do: * @code * KDNSSD::PublicService *service = new KDNSSD::PublicService("My files", "_http._tcp", 80); * connect(service, SIGNAL(published(bool)), this, SLOT(wasPublished(bool))); * service->publishAsync(); * @endcode * * @author Jakub Stachowski */ class KDNSSD_EXPORT PublicService : public QObject, public ServiceBase { Q_OBJECT public: /** * Creates a service description that can be published * * If no @p name is given, the computer name is used instead. If there * is already a service with the same name, type and domain a number will * be appended to the name to make it unique. * * If no @p domain is specified, the service is published on the link-local * domain (.local). * * The subtypes can be used to specify server attributes, such * as "_anon" for anonymous FTP servers, or can specify a specific protocol * (such as a web service interface) on top of a generic protocol like SOAP. * * There is * a comprehensive list * of possible types available, but you are largely on your own for * subtypes. * * @param name a service name to use instead of the computer name * @param type service type, in the form _sometype._udp or _sometype._tcp * @param port port number, or 0 to "reserve" the service name * @param domain the domain to publish the service on (see DomainBrowser) * @param subtypes optional list of subtypes, each with a leading underscore * * @see ServiceBrowser::ServiceBrowser() */ explicit PublicService(const QString &name = QString(), const QString &type = QString(), unsigned int port = 0, const QString &domain = QString(), const QStringList &subtypes = QStringList()); ~PublicService() override; /** * Stops publishing or aborts an incomplete publish request. * * Useful when you want to disable the service for some time. * * Note that if you stop providing a service (without exiting the * application), you should stop publishing it. */ void stop(); /** * Publish the service synchronously * * The method will not return (and hence the application interface will * freeze, since KDElibs code should be executed in the main thread) * until either the service is published or publishing fails. * * published(bool) is emitted before this method returns. * * @return @c true if the service was successfully published, @c false otherwise */ bool publish(); /** * Whether the service is currently published * * @return @c true if the service is being published to the domain, * @c false otherwise */ bool isPublished() const; /** * Publish the service asynchronously * * Returns immediately and emits published(bool) when completed. * Note that published(bool) may be emitted before this method * returns when an error is detected immediately. */ void publishAsync(); /** * Sets new text properties * * If the service is already published, it will be re-announced with * the new data. * * @param textData the new text properties for the service * * @see ServiceBase::textData() */ void setTextData(const QMap &textData); /** * Sets the name of the service * * If the service is already published, it will be re-announced with * the new name. * * @param serviceName the new name of the service */ void setServiceName(const QString &serviceName); /** * Sets the service type * * If the service is already published, it will be re-announced with * the new type. * * @param type the new type of the service * * See PublicService() for details on the format of @p type */ void setType(const QString &type); /** * Sets the subtypetypes of the service * * If the service is already published, it will be re-announced with * the new subtypes. * * The existing list of substypes is replaced, so an empty list will * cause all existing subtypes to be removed. * * @param subtypes the new list of subtypes */ void setSubTypes(const QStringList &subtypes); /** * Sets the port * * If the service is already published, it will be re-announced with * the new port. * * @param port the port of the service, or 0 to simply "reserve" the name */ void setPort(unsigned short port); /** * Sets the domain where the service is published * * "local." means link-local, ie: the IP subnet on the LAN containing * this computer. * * If service is already published, it will be removed from the current * domain and published on @p domain instead. * * @param domain the new domain to publish the service on */ void setDomain(const QString &domain); /** * The subtypes of service. * * @see setSubTypes() */ QStringList subtypes() const; Q_SIGNALS: /** * Emitted when publishing is complete * * It will also emitted when an already-published service is * republished after a property of the service (such as the * name or port) is changed. */ void published(bool successful); private: friend class PublicServicePrivate; protected: void virtual_hook(int, void *) override; }; } #endif diff --git a/src/remoteservice.h b/src/remoteservice.h index 542d73a..e8162ac 100644 --- a/src/remoteservice.h +++ b/src/remoteservice.h @@ -1,140 +1,128 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004, 2005 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004, 2005 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef KDNSSDREMOTESERVICE_H #define KDNSSDREMOTESERVICE_H #include #include #include namespace KDNSSD { class RemoteServicePrivate; /** * @class RemoteService remoteservice.h KDNSSD/RemoteService * @short Describes a service published over DNS-SD, * typically on a remote machine * * This class allows delayed or asynchronous resolution of * services. As the name suggests, the service is normally * on a remote machine, but the service could just as easily * be published on the local machine. * * RemoteService instances are normally provided by ServiceBrowser, * but can be used to resolve any service if you know the name, type * and domain for it. * * @author Jakub Stachowski * * @see ServiceBrowser */ class KDNSSD_EXPORT RemoteService : public QObject, public ServiceBase { Q_OBJECT public: typedef QExplicitlySharedDataPointer Ptr; /** * Creates an unresolved RemoteService representing the service with * the given name, type and domain * * @param name the name of the service * @param type the type of the service (see ServiceBrowser::ServiceBrowser()) * @param domain the domain of the service * * @see ServiceBrowser::isAvailable() */ RemoteService(const QString &name, const QString &type, const QString &domain); ~RemoteService() override; /** * Resolves the host name and port of service asynchronously * * The host name is not resolved into an IP address - use KResolver * for that. * * The resolved(bool) signal will be emitted when the * resolution is complete, or when it fails. * * Note that resolved(bool) may be emitted before this function * returns in case of immediate failure. * * RemoteService will keep monitoring the service for * changes in hostname and port, and re-emit resolved(bool) * when either changes. * * @see resolve(), hostName(), port() */ void resolveAsync(); /** * Resolves the host name and port of service synchronously * * The host name is not resolved into an IP address - use KResolver * for that. * * resolved(bool) is emitted before this function is returned. * * resolve() will not cause RemoteService to monitor for changes * in the hostname or port of the service. * * @return @c true if successful, @c false on failure * * @see resolveAsync(), hostName(), port() */ bool resolve(); /** * Whether the service has been successfully resolved * * @return @c true if hostName() and port() will return * valid values, @c false otherwise */ bool isResolved() const; Q_SIGNALS: /** * Emitted when resolving is complete * * If operating in asynchronous mode this signal can be * emitted several times (when the hostName or port of * the service changes). * * @param successful @c true if the hostName and port were * successfully resolved, @c false otherwise */ void resolved(bool successful); protected: void virtual_hook(int id, void *data) override; private: friend class RemoteServicePrivate; }; } Q_DECLARE_METATYPE(KDNSSD::RemoteService::Ptr) #endif diff --git a/src/servicebase.cpp b/src/servicebase.cpp index 912ca37..0896f18 100644 --- a/src/servicebase.cpp +++ b/src/servicebase.cpp @@ -1,91 +1,79 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "servicebase.h" #include "servicebase_p.h" #include #include #include namespace KDNSSD { ServiceBase::ServiceBase(const QString &name, const QString &type, const QString &domain, const QString &host, unsigned short port) : d(new ServiceBasePrivate(name, type, domain, host, port)) {} ServiceBase::ServiceBase(ServiceBasePrivate *const _d) : d(_d) {} ServiceBase::~ServiceBase() { delete d; } QString ServiceBase::serviceName() const { return d->m_serviceName; } QString ServiceBase::type() const { return d->m_type; } QString ServiceBase::domain() const { return d->m_domain; } QString ServiceBase::hostName() const { return d->m_hostName; } unsigned short ServiceBase::port() const { return d->m_port; } QMap ServiceBase::textData() const { return d->m_textData; } bool ServiceBase::operator==(const ServiceBase &o) const { return d->m_domain == o.d->m_domain && d->m_serviceName == o.d->m_serviceName && d->m_type == o.d->m_type; } bool ServiceBase::operator!=(const ServiceBase &o) const { return !(*this == o); } void ServiceBase::virtual_hook(int, void *) {} bool domainIsLocal(const QString &domain) { return domain.section(QLatin1Char('.'), -1, -1).toLower() == QLatin1String("local"); } } diff --git a/src/servicebase.h b/src/servicebase.h index 25f9975..def54a2 100644 --- a/src/servicebase.h +++ b/src/servicebase.h @@ -1,204 +1,192 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef KDNSSDSERVICEBASE_H #define KDNSSDSERVICEBASE_H #include #include #include #include namespace KDNSSD { class ServiceBasePrivate; /** * @class ServiceBase servicebase.h KDNSSD/ServiceBase * @short Describes a service * * This class is used to describe a service. The service * can be published by the current application (in which * case it is probably a PublicService) or by * another application, either on the current machine or * a remote machine, in which case it is probably a * RemoteService returned by ServiceBrowser. * * You should not normally need to create a ServiceBase * object yourself. * * @author Jakub Stachowski * * @see PublicService */ class KDNSSD_EXPORT ServiceBase : public QSharedData //krazy:exclude=dpointer (protected) { public: typedef QExplicitlySharedDataPointer Ptr; /** * Creates a ServiceBase object * * Note that @p name, @p type and @p domain uniquely identify * the service in the DNS-SD system, and @p host and @p port * provide the actual location of the service. * * For example, RemoteService populates @p host and @p port * based on the @p name, @p type and @p domain attributes * using the DNS-SD resolution system. * * @param name service name * @param type service type * @param domain the DNS-SD domain name for service * @param host the host name of the service (a fully-qualified domain name) * @param port the port number of the service */ explicit ServiceBase(const QString &name = QString(), const QString &type = QString(), const QString &domain = QString(), const QString &host = QString(), unsigned short port = 0); virtual ~ServiceBase(); /** * The name of the service */ QString serviceName() const; /** * The type of the service * * This is always in the format _sometype._udp or _sometype._tcp. * * See the DNS-SD website for * a full list of service types. */ QString type() const; /** * The domain that the service belongs to * * It is "local." for link-local services. */ QString domain() const; /** * The hostname of the service * * Only valid for local and resolved remote services. * * Together with port(), this can be used to actually * access the service. * * @see RemoteService::resolve() and RemoteService::resolveAsync() */ QString hostName() const; /** * The port number of the service * * Only valid for local and resolved remote services. * * Together with hostName(), this can be used to actually * access the service. * * @see RemoteService::resolve() and RemoteService::resolveAsync() */ unsigned short port() const; /** * Additional text data associated with the service * * Only valid for local and resolved remote services. * * This is data that provides additional information about the * service. For example, it might be used to specify a printer * queue on the printer server specified by hostName() and port(). * * You can check for the data that might be associated with a * particular service on the service types list. * If a @c key=value pair is given, this will appear with the @c value * in a QByteArray indexed by the @c key. If the data is on its own * (does not have an @c = in it), it will be used to index an empty * QByteArray, and can be checked for with QMap::contains(). * * For example, if you are accessing the _ipp._tcp service, you might * do something like * @code * QString printerModel = "unknown"; * if (service->textData().contains("ty")) { * printQueue = QString::fromUtf8(service->textData()["ty"].constData()); * } * @endcode * since the TXT data of the IPP service may contain data like * "ty=Apple LaserWriter Pro 630". Note that you actually have to be * a bit more clever than this, since the key should usually be case * insensitive. */ QMap textData() const; /** * Compares services based on name, type and domain * * This is enough to for unique identification and omitting * port, host and text data allows to compare resolved and * unresolved services * * @param o the service to compare this service to * @return @c true if this service represents the same * service (from the point of view of DNS-SD) as * @p o, @c false otherwise */ bool operator==(const ServiceBase &o) const; /** * Compares services based on name, type and domain * * This is enough to for unique identification and omitting * port, host and text data allows to compare resolved and * unresolved services * * @param o the service to compare this service to * @return @c false if this service represents the same * service (from the point of view of DNS-SD) as * @p o, @c true otherwise */ bool operator!=(const ServiceBase &o) const; protected: ServiceBase(ServiceBasePrivate *const d); virtual void virtual_hook(int, void *); ServiceBasePrivate *const d; }; /* Utility functions */ /** * Check if the domain is link-local * * @return @c true if domain is link-local ('local.'), @c false otherwise */ bool domainIsLocal(const QString &domain); } #endif diff --git a/src/servicebase_p.h b/src/servicebase_p.h index a8c58e6..fdde833 100644 --- a/src/servicebase_p.h +++ b/src/servicebase_p.h @@ -1,51 +1,39 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004, 2007 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004, 2007 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef SERVICEBASE_P_H #define SERVICEBASE_P_H #include #include namespace KDNSSD { class ServiceBasePrivate { public: ServiceBasePrivate(const QString &name, const QString &type, const QString &domain, const QString &host, unsigned short port) : m_serviceName(name), m_type(type), m_domain(domain), m_hostName(host), m_port(port) {} virtual ~ServiceBasePrivate() {} QString m_serviceName; QString m_type; QString m_domain; QString m_hostName; unsigned short m_port; /** Map of TXT properties */ QMap m_textData; }; } #endif diff --git a/src/servicebrowser.h b/src/servicebrowser.h index 4473816..b4803ae 100644 --- a/src/servicebrowser.h +++ b/src/servicebrowser.h @@ -1,294 +1,282 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef KDNSSDSERVICEBROWSER_H #define KDNSSDSERVICEBROWSER_H #include #include #include namespace KDNSSD { class DomainBrowser; class ServiceBrowserPrivate; /** * @class ServiceBrowser servicebrowser.h KDNSSD/ServiceBrowser * @short Browses for network services advertised over DNS-SD * * This is the central class in the KDNSSD library for applications * that want to discover services on network. * * Suppose that you need list of web servers running. Then you * might do something like * @code * KDNSSD::ServiceBrowser *browser = new KDNSSD::ServiceBrowser(QStringLiteral("_http._tcp")); * connect(browser, &KDNSSD::ServiceBrowser::serviceAdded, * this, [](KDNSSD::RemoteService::Ptr service) { * }); * connect(browser, &KDNSSD::ServiceBrowser::serviceRemoved, * this, [](KDNSSD::RemoteService::Ptr service) { * }); * browser->startBrowse(); * @endcode * * In above example addService() will be called for every web server * already running and for every web service that subsequently * appears on the network and delService() will be called when * a server previously advertised is stopped. * * Because no domain was passed to constructor, the default domain * will be searched. To find other domains to browse for services on, * use DomainBrowser. * * @author Jakub Stachowski */ class KDNSSD_EXPORT ServiceBrowser : public QObject { Q_OBJECT public: /** * Availability of DNS-SD services */ enum State { /** the service is available */ Working, /** not available because mDnsd or Avahi daemon is not running */ Stopped, /** not available because KDE was compiled without DNS-SD support */ Unsupported }; /** * Create a ServiceBrowser for a particular service type * * DomainBrowser can be used to find other domains to browse on. * If no domain is given, the default domain is used. * * The service type is the high-level protocol type, followed by a dot, * followed by the transport protocol type (@c _tcp or @c _udp). * The DNS-SD website maintains * a full list * of service types. * * The @p subtype parameter allows you to do more fine-grained filtering * on the services you are interested in. So you might request only * FTP servers that allow anonymous access by passing "_ftp._tcp" as the * @p type and "_anon" as the @p subtype. Subtypes are particularly * important for types like _soap and _upnp, which are far too generic * for most applications. In these cases, the subtype can be used to * specify the particular SOAP or UPnP protocol they want. * * @warning * Enabling @p autoResolve will increase network usage by resolving * all services, so this feature should be used only when necessary. * * @param type service types to browse for (example: "_http._tcp") * @param autoResolve discovered services will be resolved before being * reported with the serviceAdded() signal * @param domain a domain to search on instead of the default one * @param subtype only browse for a specific subtype * * @see startBrowse() and isAvailable() */ explicit ServiceBrowser(const QString &type, bool autoResolve = false, const QString &domain = QString(), const QString &subtype = QString()); ~ServiceBrowser(); /** * The currently known services of the specified type * * @returns a list of RemoteService pointers * * @see serviceAdded() and serviceRemoved() */ QList services() const; /** * Starts browsing for services * * Only the first call to this function will have any effect. * * Browsing stops when the ServiceBrowser object is destroyed. * * @warning The serviceAdded() signal may be emitted before this * function returns. * * @see serviceAdded(), serviceRemoved() and finished() */ virtual void startBrowse(); /** * Checks availability of DNS-SD services * * Although this method is part of ServiceBrowser, none of the classes * in this library will be able to perform their intended function * if this method does not return Working. * * If this method does not return Working, it is still safe to call * any of the methods in this library. However, no services will be * found or published and no domains will be found. * * If you use this function to report an error to the user, below * is a suggestion on how to word the errors when publishing a * service. The first line of each error message can also be * used for reporting errors when browsing for services. * * @code * switch(KDNSSD::ServiceBrowser::isAvailable()) { * case KDNSSD::ServiceBrowser::Working: * return ""; * case KDNSSD::ServiceBrowser::Stopped: * return i18n("

The Zeroconf daemon is not running. See the Service" * " Discovery Handbook for more information.
" * "Other users will not see the services provided by this * " system when browsing the network via zeroconf, but " * " normal access will still work.

"); * case KDNSSD::ServiceBrowser::Unsupported: * return i18n("

Zeroconf support is not available in this version of KDE." * " See the Service Discovery Handbook for more information.
" * "Other users will not see the services provided by this * " application when browsing the network via zeroconf, but " * " normal access will still work.

"); * default: * return i18n("

Unknown error with Zeroconf.
" * "Other users will not see the services provided by this * " application when browsing the network via zeroconf, but " * " normal access will still work.

"); * } * @endcode * */ static State isAvailable(); /** * Whether discovered services are resolved before being reported * * @return the value of the @p autoResolve parameter passed to the constructor * * @since 4.1 */ bool isAutoResolving() const; /** * Resolves an mDNS hostname into an IP address * * This function is very rarely useful, since a properly configured * system is able to resolve an mDNS-based host name using the system * resolver (ie: you can just pass the mDNS hostname to KIO or other * library). * * @param hostname the hostname to be resolved * @return a QHostAddress containing the IP address, or QHostAddress() if * resolution failed * @since 4.2 */ static QHostAddress resolveHostName(const QString &hostname); /** * The mDNS hostname of the local machine * * Usually this will return the same as QHostInfo::localHostName(), * but it may be changed to something different * in the Avahi configuration file (if using the Avahi backend). * * @return the hostname, or an empty string on failure * @since 4.2 */ static QString getLocalHostName(); Q_SIGNALS: /** * Emitted when new service is discovered * * If isAutoResolving() returns @c true, this will not be emitted * until the service has been resolved. * * @param service a RemoteService object describing the service * * @see serviceRemoved() and finished() */ void serviceAdded(KDNSSD::RemoteService::Ptr service); /** * Emitted when a service is no longer published over DNS-SD * * The RemoteService object is removed from the services() list * and deleted immediately after this signal returns. * * @warning * Do @b not use a delayed connection with this signal * * @param service a RemoteService object describing the service * * @see serviceAdded() and finished() */ void serviceRemoved(KDNSSD::RemoteService::Ptr service); /** * Emitted when the list of published services has settled * * This signal is emitted once after startBrowse() is called * when all the services of the requested type that are * currently published have been reported (even if none * are available or the DNS-SD service is not available). * It is emitted again when a new batch of services become * available or disappear. * * For example, if a new host is connected to network and * announces some services watched for by this ServiceBrowser, * they will be reported by one or more serviceAdded() signals * and the whole batch will be concluded by finished(). * * This signal can be used by applications that just want to * get a list of the currently available services * (similar to a directory listing) and do not care about * adding or removing services that appear or disappear later. * * @warning * There is no guarantee any RemoteService * pointers received by serviceAdded() will be valid * by the time this signal is emitted, so you should either * do all your work involving them in the slot receiving * the serviceAdded() signal, or you should listen to * serviceRemoved() as well. * * @see serviceAdded() and serviceRemoved() */ void finished(); protected: virtual void virtual_hook(int, void *); private: friend class ServiceBrowserPrivate; ServiceBrowserPrivate *const d; }; } #endif diff --git a/src/servicemodel.cpp b/src/servicemodel.cpp index 392959d..5bcea20 100644 --- a/src/servicemodel.cpp +++ b/src/servicemodel.cpp @@ -1,119 +1,107 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2008 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2008 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #include "servicemodel.h" #include "servicebrowser.h" namespace KDNSSD { struct ServiceModelPrivate { ServiceBrowser *m_browser; }; ServiceModel::ServiceModel(ServiceBrowser *browser, QObject *parent) : QAbstractItemModel(parent), d(new ServiceModelPrivate) { d->m_browser = browser; browser->setParent(this); connect(browser, SIGNAL(serviceAdded(KDNSSD::RemoteService::Ptr)), this, SIGNAL(layoutChanged())); connect(browser, SIGNAL(serviceRemoved(KDNSSD::RemoteService::Ptr)), this, SIGNAL(layoutChanged())); browser->startBrowse(); } ServiceModel::~ServiceModel() { delete d; } int ServiceModel::columnCount(const QModelIndex &) const { return d->m_browser->isAutoResolving() ? 3 : 1; } int ServiceModel::rowCount(const QModelIndex &parent) const { return (parent.isValid()) ? 0 : d->m_browser->services().size(); } QModelIndex ServiceModel::parent(const QModelIndex &) const { return QModelIndex(); } QModelIndex ServiceModel::index(int row, int column, const QModelIndex &parent) const { return hasIndex(row, column, parent) ? createIndex(row, column) : QModelIndex(); } bool ServiceModel::hasIndex(int row, int column, const QModelIndex &parent) const { if (parent.isValid()) { return false; } if (column < 0 || column >= columnCount()) { return false; } if (row < 0 || row >= rowCount(parent)) { return false; } return true; } QVariant ServiceModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (!hasIndex(index.row(), index.column(), index.parent())) { return QVariant(); } const QList srv = d->m_browser->services(); switch ((uint)role) { case Qt::DisplayRole: switch (index.column()) { case ServiceName: return srv[index.row()]->serviceName(); case Host: return srv[index.row()]->hostName(); case Port: return srv[index.row()]->port(); } break; - case ServicePtrRole: + case ServicePtrRole: QVariant ret; ret.setValue(srv[index.row()]); return ret; } return QVariant(); } QVariant ServiceModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation != Qt::Horizontal || role != Qt::DisplayRole) { return QVariant(); } switch (section) { case ServiceName: return tr("Name"); case Host: return tr("Host"); case Port: return tr("Port"); } return QVariant(); } } diff --git a/src/servicemodel.h b/src/servicemodel.h index 08170d3..7d6ad62 100644 --- a/src/servicemodel.h +++ b/src/servicemodel.h @@ -1,125 +1,113 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2008 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2008 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef KDNSSDSERVICEMODEL_H #define KDNSSDSERVICEMODEL_H #include #include #include namespace KDNSSD { struct ServiceModelPrivate; class ServiceBrowser; /** * @class ServiceModel servicemodel.h KDNSSD/ServiceModel * @short Model for list of Zeroconf services * * This class provides a Qt Model for ServiceBrowser to allow easy * integration of service discovery into a GUI. For example, to * show the HTTP servers published on the local network, you can do: * @code * KDNSSD::ServiceModel *serviceModel = new ServiceModel( * new KDNSSD::ServiceBrowser("_http._tcp") * ); * QComboBox *serviceCombo = new QComboBox(); * serviceCombo->setModel(serviceModel); * @endcode * * After the user makes a selection, the application typically needs * to get a pointer to the selected service in order to get the host * name and port. A RemoteService::Ptr can be obtained from * a QModelIndex using: * @code * void onSelected(const QModelIndex &selection) { * KDNSSD::RemoteService::Ptr service = * selection.data(KDNSSD::ServiceModel::ServicePtrRole) * .value(); * } * @endcode * * @since 4.1 * @author Jakub Stachowski */ class KDNSSD_EXPORT ServiceModel : public QAbstractItemModel { Q_OBJECT public: /** The additional data roles provided by this model */ enum AdditionalRoles { ServicePtrRole = 0xA06519DE ///< gets a RemoteService::Ptr for the service }; /** * The default columns for this model. * * If service browser is not set to resolve automatically, * then the model will only ever have one column (the service name). */ enum ModelColumns { ServiceName = 0, Host = 1, Port = 2 }; /** * Creates a model for the given service browser and starts browsing * for services. * * The model takes ownership of the browser, * so there is no need to delete it afterwards. * * You should @b not call ServiceBrowser::startBrowse() on @p browser * before passing it to ServiceModel. */ explicit ServiceModel(ServiceBrowser *browser, QObject *parent = nullptr); ~ServiceModel() override; /** @reimp */ int columnCount(const QModelIndex &parent = QModelIndex()) const override; /** @reimp */ int rowCount(const QModelIndex &parent = QModelIndex()) const override; /** @reimp */ QModelIndex parent(const QModelIndex &index) const override; /** @reimp */ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; /** @reimp */ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; /** @reimp */ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; /** @reimp */ virtual bool hasIndex(int row, int column, const QModelIndex &parent) const; private: ServiceModelPrivate *const d; friend struct ServiceModelPrivate; }; } #endif diff --git a/src/servicetypebrowser.h b/src/servicetypebrowser.h index e4535dc..27141d7 100644 --- a/src/servicetypebrowser.h +++ b/src/servicetypebrowser.h @@ -1,159 +1,147 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2004 Jakub Stachowski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ +/* + This file is part of the KDE project + + SPDX-FileCopyrightText: 2004 Jakub Stachowski + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ #ifndef KDNSSDSERVICETYPEBROWSER_H #define KDNSSDSERVICETYPEBROWSER_H #include #include class QStringList; namespace KDNSSD { class ServiceTypeBrowserPrivate; /** * @class ServiceTypeBrowser servicetypebrowser.h KDNSSD/ServiceTypeBrowser * @short Browses the service types being published on a domain * * This class is mostly useful for generic utilities for * browsing all the published service types on a local network. * Applications that wish to find out about available services * of a particular type (such as web servers) should use * ServiceBrowser. * * ServiceTypeBrowser provides a list of all the service types * published by at least one service on a given domain. * * @author Jakub Stachowski */ class KDNSSD_EXPORT ServiceTypeBrowser : public QObject { Q_OBJECT public: /** * Create a ServiceTypeBrowser for a domain * * The link-local domain (the LAN subnet for this computer) will * be used if no @p domain is given. DomainBrowser can be used * to get a list of browsing domains. * * Note that WAN domains may not support service type browsing. * * @param domain a browsing domain to search * @param parent the parent object (see QObject documentation) * * @see startBrowse() and ServiceBrowser::isAvailable() */ explicit ServiceTypeBrowser(const QString &domain = QString(), QObject *parent = nullptr); ~ServiceTypeBrowser(); /** * All the service types currently being published * * @return a list of service types, in the form _type._tcp or _type._udp */ QStringList serviceTypes() const; /** * Starts browsing * * Only the first call to this function will have any effect. * * Browsing stops when the ServiceTypeBrowser object is destroyed. * * @warning The serviceTypeAdded() signal may be emitted before this * function returns. * * @see serviceTypeAdded(), serviceTypeRemoved() and finished() */ void startBrowse(); #if KDNSSD_ENABLE_DEPRECATED_SINCE(4, 0) /** * This method is unnecessary, since it is safe to call startBrowse() * multiple times. * @deprecated since 4.0, just call startBrowse() again. */ KDNSSD_DEPRECATED_VERSION(4, 0, "Just call ServiceTypeBrowser::startBrowse() again") bool isRunning() const { return false; } #endif Q_SIGNALS: /** * Emitted when there are no more services of this type * * @warning * This signal is not reliable: it is possible that it will not be * emitted even after last service of this type disappeared * * @param type the service type * * @see serviceTypeAdded() and finished() */ void serviceTypeRemoved(const QString &type); /** * A new type of service has been found * * @param type the service type * * @see serviceTypeAdded() and finished() */ void serviceTypeAdded(const QString &type); /** * Emitted when the list of published service types has settled * * This signal is emitted once after startBrowse() is called * when the types of all the services that are * currently published have been reported (even if no services * are available or the DNS-SD service is not available). * It is emitted again when a new batch of service types become * available or disappear. * * For example, if a new host is connected to network and * announces services of several new types, * they will be reported by several serviceTypeAdded() signals * and the whole batch will be concluded by finished(). * * This signal can be used by applications that just want to * get a list of the currently available service types * (similar to a directory listing) and do not care about * adding or removing service types that appear or disappear later. * * @see serviceTypeAdded() and serviceTypeRemoved() */ void finished(); private: friend class ServiceTypeBrowserPrivate; ServiceTypeBrowserPrivate *const d; }; } #endif