1 /*
2 * Copyright (C) 2013 Andreas Degert
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 * ---------------------------------------------------------------------------
18 */
19
20 #include <avahi-common/error.h>
21 #include <avahi-common/alternative.h>
22 #include <avahi-common/malloc.h>
23 #include "avahi_register.h"
24 #include "gx_logging.h"
25
26 /****************************************************************
27 ** class AvahiService
28 */
29
AvahiService()30 AvahiService::AvahiService()
31 : client(0), group(0), current_name(), registered_port(-1) {
32 client = ga_client_new(GaClientFlags(0));
33 GError *error = 0;
34 if (!ga_client_start(client, &error)) {
35 gx_print_error("avahi registration", error->message);
36 return;
37 }
38 group = ga_entry_group_new();
39 g_signal_connect(group, "state-changed", G_CALLBACK(state_changed), this);
40 error = 0;
41 ga_entry_group_attach(group, client, &error);
42 }
43
~AvahiService()44 AvahiService::~AvahiService() {
45 if (client) {
46 g_clear_object(&client);
47 }
48 if (group) {
49 g_clear_object(&group);
50 }
51 }
52
53 //static
state_changed(GaEntryGroup * group,GaEntryGroupState state,void * data)54 void AvahiService::state_changed(GaEntryGroup *group, GaEntryGroupState state, void *data) {
55 AvahiService& self = *static_cast<AvahiService*>(data);
56 switch (state) {
57 case GA_ENTRY_GROUP_STATE_UNCOMMITED: break;
58 case GA_ENTRY_GROUP_STATE_REGISTERING: break;
59 case GA_ENTRY_GROUP_STATE_ESTABLISHED:
60 gx_print_info("avahi registration", "established");
61 break;
62 case GA_ENTRY_GROUP_STATE_COLLISTION: { // typo in header??
63 gx_print_info("avahi registration", "collision");
64 char *n = avahi_alternative_service_name(self.current_name.c_str());
65 std::string name = n;
66 avahi_free(n);
67 self.register_service(name, self.registered_port);
68 break;
69 }
70 case GA_ENTRY_GROUP_STATE_FAILURE:
71 gx_print_error("avahi registration", "failure");
72 break;
73 }
74 }
75
register_service(std::string name,int port)76 bool AvahiService::register_service(std::string name, int port) {
77 if (!group) {
78 return false;
79 }
80 for (int i = 0; i < 10; ++i) {
81 GError *error = 0;
82 ga_entry_group_add_service(group, name.c_str(), "_guitarix._tcp", port, &error, 0);
83 if (!error) {
84 break;
85 }
86 if (error->code != AVAHI_ERR_COLLISION) {
87 gx_print_error("avahi registration", error->message);
88 return false;
89 }
90 char *n = avahi_alternative_service_name(name.c_str());
91 name = n;
92 avahi_free(n);
93 }
94 ga_entry_group_commit(group, 0);
95 current_name = name;
96 registered_port = port;
97 return true;
98 }
99