1 /*
2  * Copyright 2003-2021 The Music Player Daemon Project
3  * http://www.musicpd.org
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include "Glue.hxx"
21 #include "Helper.hxx"
22 #include "config/Data.hxx"
23 #include "config/Option.hxx"
24 #include "Listen.hxx"
25 #include "util/Domain.hxx"
26 #include "Log.hxx"
27 #include "util/Compiler.h"
28 
29 #ifdef HAVE_AVAHI
30 #include "avahi/Helper.hxx"
31 #endif
32 
33 #ifdef HAVE_BONJOUR
34 #include "Bonjour.hxx"
35 #endif
36 
37 #include <climits>
38 
39 #include <string.h>
40 #include <unistd.h>
41 
42 #ifndef HOST_NAME_MAX
43 /* HOST_NAME_MAX is not a portable macro; it is undefined on some
44    systems */
45 #define HOST_NAME_MAX 255
46 #endif
47 
48 static constexpr Domain zeroconf_domain("zeroconf");
49 
50 /* The default service name to publish
51  * (overridden by 'zeroconf_name' config parameter)
52  */
53 #define SERVICE_NAME		"Music Player @ %h"
54 
55 /* The dns-sd service type qualifier to publish */
56 #define SERVICE_TYPE		"_mpd._tcp"
57 
58 #define DEFAULT_ZEROCONF_ENABLED 1
59 
60 std::unique_ptr<ZeroconfHelper>
ZeroconfInit(const ConfigData & config,EventLoop & loop)61 ZeroconfInit(const ConfigData &config, [[maybe_unused]] EventLoop &loop)
62 {
63 	const char *serviceName;
64 
65 	if (!config.GetBool(ConfigOption::ZEROCONF_ENABLED,
66 			    DEFAULT_ZEROCONF_ENABLED))
67 		return nullptr;
68 
69 	if (listen_port <= 0) {
70 		LogWarning(zeroconf_domain,
71 			   "No global port, disabling zeroconf");
72 		return nullptr;
73 	}
74 
75 	serviceName = config.GetString(ConfigOption::ZEROCONF_NAME,
76 				       SERVICE_NAME);
77 
78 	/* replace "%h" with the host name */
79 	const char *h = strstr(serviceName, "%h");
80 	std::string buffer;
81 	if (h != nullptr) {
82 		char hostname[HOST_NAME_MAX+1];
83 		if (gethostname(hostname, HOST_NAME_MAX) == 0) {
84 			buffer = serviceName;
85 			buffer.replace(h - serviceName, 2, hostname);
86 			serviceName = buffer.c_str();
87 		}
88 	}
89 
90 	return std::make_unique<ZeroconfHelper>(loop, serviceName,
91 						SERVICE_TYPE, listen_port);
92 }
93