1/* $Id$ */ 2 3/*** 4 This file is part of avahi. 5 6 avahi is free software; you can redistribute it and/or modify it 7 under the terms of the GNU Lesser General Public License as 8 published by the Free Software Foundation; either version 2.1 of the 9 License, or (at your option) any later version. 10 11 avahi is distributed in the hope that it will be useful, but WITHOUT 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General 14 Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with avahi; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 19 USA. 20***/ 21 22#ifdef HAVE_CONFIG_H 23#include <config.h> 24#endif 25 26#include <string.h> 27#include <sys/ioctl.h> 28#include <sys/types.h> 29#include <sys/socket.h> 30#include <netinet/in.h> 31#include <net/if.h> 32#include <errno.h> 33#include <unistd.h> 34#include <assert.h> 35#include <sys/stat.h> 36#include <fcntl.h> 37#include <stdio.h> 38#include <signal.h> 39#include <stdlib.h> 40 41#include <dbus/dbus.h> 42 43#include <avahi-common/dbus.h> 44#include <avahi-common/llist.h> 45#include <avahi-common/malloc.h> 46#include <avahi-common/dbus-watch-glue.h> 47#include <avahi-common/alternative.h> 48#include <avahi-common/error.h> 49#include <avahi-common/domain.h> 50#include <avahi-common/timeval.h> 51 52#include <avahi-core/log.h> 53#include <avahi-core/core.h> 54#include <avahi-core/lookup.h> 55#include <avahi-core/publish.h> 56 57#include "dbus-protocol.h" 58#include "dbus-util.h" 59#include "dbus-internal.h" 60#include "main.h" 61 62/* #define VALGRIND_WORKAROUND 1 */ 63 64#define RECONNECT_MSEC 3000 65 66Server *server = NULL; 67 68static int disable_user_service_publishing = 0; 69 70static int dbus_connect(void); 71static void dbus_disconnect(void); 72 73static void client_free(Client *c) { 74 75 assert(server); 76 assert(c); 77 78 while (c->entry_groups) 79 avahi_dbus_entry_group_free(c->entry_groups); 80 81 while (c->sync_host_name_resolvers) 82 avahi_dbus_sync_host_name_resolver_free(c->sync_host_name_resolvers); 83 84 while (c->async_host_name_resolvers) 85 avahi_dbus_async_host_name_resolver_free(c->async_host_name_resolvers); 86 87 while (c->sync_address_resolvers) 88 avahi_dbus_sync_address_resolver_free(c->sync_address_resolvers); 89 90 while (c->async_address_resolvers) 91 avahi_dbus_async_address_resolver_free(c->async_address_resolvers); 92 93 while (c->domain_browsers) 94 avahi_dbus_domain_browser_free(c->domain_browsers); 95 96 while (c->service_type_browsers) 97 avahi_dbus_service_type_browser_free(c->service_type_browsers); 98 99 while (c->service_browsers) 100 avahi_dbus_service_browser_free(c->service_browsers); 101 102 while (c->sync_service_resolvers) 103 avahi_dbus_sync_service_resolver_free(c->sync_service_resolvers); 104 105 while (c->async_service_resolvers) 106 avahi_dbus_async_service_resolver_free(c->async_service_resolvers); 107 108 while (c->record_browsers) 109 avahi_dbus_record_browser_free(c->record_browsers); 110 111 assert(c->n_objects == 0); 112 113 avahi_free(c->name); 114 AVAHI_LLIST_REMOVE(Client, clients, server->clients, c); 115 avahi_free(c); 116 117 server->n_clients --; 118 assert(server->n_clients >= 0); 119} 120 121static Client *client_get(const char *name, int create) { 122 Client *client; 123 124 assert(server); 125 assert(name); 126 127 for (client = server->clients; client; client = client->clients_next) 128 if (!strcmp(name, client->name)) 129 return client; 130 131 if (!create) 132 return NULL; 133 134 if (server->n_clients >= CLIENTS_MAX) 135 return NULL; 136 137 /* If not existent yet, create a new entry */ 138 client = avahi_new(Client, 1); 139 client->id = server->current_id++; 140 client->name = avahi_strdup(name); 141 client->current_id = 0; 142 client->n_objects = 0; 143 144 AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups); 145 AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers); 146 AVAHI_LLIST_HEAD_INIT(AsyncHostNameResolverInfo, client->async_host_name_resolvers); 147 AVAHI_LLIST_HEAD_INIT(SyncAddressResolverInfo, client->sync_address_resolvers); 148 AVAHI_LLIST_HEAD_INIT(AsyncAddressResolverInfo, client->async_address_resolvers); 149 AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers); 150 AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers); 151 AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers); 152 AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers); 153 AVAHI_LLIST_HEAD_INIT(AsyncServiceResolverInfo, client->async_service_resolvers); 154 AVAHI_LLIST_HEAD_INIT(RecordBrowserInfo, client->record_browsers); 155 156 AVAHI_LLIST_PREPEND(Client, clients, server->clients, client); 157 158 server->n_clients++; 159 assert(server->n_clients > 0); 160 161 return client; 162} 163 164static void reconnect_callback(AvahiTimeout *t, AVAHI_GCC_UNUSED void *userdata) { 165 assert(!server->bus); 166 167 if (dbus_connect() < 0) { 168 struct timeval tv; 169 avahi_log_debug(__FILE__": Connection failed, retrying in %ims...", RECONNECT_MSEC); 170 avahi_elapse_time(&tv, RECONNECT_MSEC, 0); 171 server->poll_api->timeout_update(t, &tv); 172 } else { 173 avahi_log_debug(__FILE__": Successfully reconnected."); 174 server->poll_api->timeout_update(t, NULL); 175 } 176} 177 178static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) { 179 DBusError error; 180 181 dbus_error_init(&error); 182 183/* avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", */ 184/* dbus_message_get_interface(m), */ 185/* dbus_message_get_path(m), */ 186/* dbus_message_get_member(m)); */ 187 188 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) { 189 struct timeval tv; 190 191 if (server->reconnect) { 192 avahi_log_warn("Disconnected from D-Bus, trying to reconnect in %ims...", RECONNECT_MSEC); 193 194 dbus_disconnect(); 195 196 avahi_elapse_time(&tv, RECONNECT_MSEC, 0); 197 198 if (server->reconnect_timeout) 199 server->poll_api->timeout_update(server->reconnect_timeout, &tv); 200 else 201 server->reconnect_timeout = server->poll_api->timeout_new(server->poll_api, &tv, reconnect_callback, NULL); 202 } else { 203 avahi_log_warn("Disconnected from D-Bus, exiting."); 204 raise(SIGQUIT); 205 } 206 207 return DBUS_HANDLER_RESULT_HANDLED; 208 209 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) { 210 char *name; 211 212 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) { 213 avahi_log_warn("Error parsing NameAcquired message"); 214 goto fail; 215 } 216 217/* avahi_log_info(__FILE__": name acquired (%s)", name); */ 218 return DBUS_HANDLER_RESULT_HANDLED; 219 220 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) { 221 char *name, *old, *new; 222 223 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) { 224 avahi_log_warn("Error parsing NameOwnerChanged message"); 225 goto fail; 226 } 227 228 if (!*new) { 229 Client *client; 230 231 if ((client = client_get(name, FALSE))) { 232 avahi_log_debug(__FILE__": client %s vanished.", name); 233 client_free(client); 234 } 235 } 236 } 237 238fail: 239 if (dbus_error_is_set(&error)) 240 dbus_error_free(&error); 241 242 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 243} 244 245static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) { 246 DBusError error; 247 248 dbus_error_init(&error); 249 250 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", 251 dbus_message_get_interface(m), 252 dbus_message_get_path(m), 253 dbus_message_get_member(m)); 254 255 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect")) 256 return avahi_dbus_handle_introspect(c, m, "Server.introspect"); 257 258 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) { 259 260 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { 261 avahi_log_warn("Error parsing Server::GetHostName message"); 262 goto fail; 263 } 264 265 return avahi_dbus_respond_string(c, m, avahi_server_get_host_name(avahi_server)); 266 267 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "SetHostName")) { 268 269 char *name; 270 271 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) { 272 avahi_log_warn("Error parsing Server::SetHostName message"); 273 goto fail; 274 } 275 276 if (avahi_server_set_host_name(avahi_server, name) < 0) 277 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 278 279 avahi_log_info("Changing host name to '%s'.", name); 280 281 return avahi_dbus_respond_ok(c, m); 282 283 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) { 284 285 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { 286 avahi_log_warn("Error parsing Server::GetDomainName message"); 287 goto fail; 288 } 289 290 return avahi_dbus_respond_string(c, m, avahi_server_get_domain_name(avahi_server)); 291 292 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) { 293 294 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) { 295 avahi_log_warn("Error parsing Server::GetHostNameFqdn message"); 296 goto fail; 297 } 298 299 return avahi_dbus_respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server)); 300 301 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsNSSSupportAvailable")) { 302 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) { 303 avahi_log_warn("Error parsing Server::IsNSSSupportAvailable message"); 304 goto fail; 305 } 306 307 return avahi_dbus_respond_boolean(c, m, nss_support); 308 309 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) { 310 311 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) { 312 avahi_log_warn("Error parsing Server::GetVersionString message"); 313 goto fail; 314 } 315 316 return avahi_dbus_respond_string(c, m, PACKAGE_STRING); 317 318 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAPIVersion")) { 319 320 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) { 321 avahi_log_warn("Error parsing Server::GetAPIVersion message"); 322 goto fail; 323 } 324 325 return avahi_dbus_respond_uint32(c, m, AVAHI_DBUS_API_VERSION); 326 327 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) { 328 AvahiServerState state; 329 330 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) { 331 avahi_log_warn("Error parsing Server::GetState message"); 332 goto fail; 333 } 334 335 state = avahi_server_get_state(avahi_server); 336 return avahi_dbus_respond_int32(c, m, (int32_t) state); 337 338 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) { 339 340 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) { 341 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message"); 342 goto fail; 343 } 344 345 return avahi_dbus_respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server)); 346 347 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) { 348 int32_t idx; 349 char name[IF_NAMESIZE]; 350 351 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) { 352 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message"); 353 goto fail; 354 } 355 356#ifdef VALGRIND_WORKAROUND 357 return respond_string(c, m, "blah"); 358#else 359 if ((!if_indextoname(idx, name))) { 360 char txt[256]; 361 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno)); 362 return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt); 363 } 364 365 return avahi_dbus_respond_string(c, m, name); 366#endif 367 368 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) { 369 char *n; 370 int32_t idx; 371 372 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) { 373 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message"); 374 goto fail; 375 } 376 377#ifdef VALGRIND_WORKAROUND 378 return respond_int32(c, m, 1); 379#else 380 if (!(idx = if_nametoindex(n))) { 381 char txt[256]; 382 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno)); 383 return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt); 384 } 385 386 return avahi_dbus_respond_int32(c, m, idx); 387#endif 388 389 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) { 390 char *n, * t; 391 392 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) { 393 avahi_log_warn("Error parsing Server::GetAlternativeHostName message"); 394 goto fail; 395 } 396 397 t = avahi_alternative_host_name(n); 398 avahi_dbus_respond_string(c, m, t); 399 avahi_free(t); 400 401 return DBUS_HANDLER_RESULT_HANDLED; 402 403 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) { 404 char *n, *t; 405 406 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) { 407 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message"); 408 goto fail; 409 } 410 411 t = avahi_alternative_service_name(n); 412 avahi_dbus_respond_string(c, m, t); 413 avahi_free(t); 414 415 return DBUS_HANDLER_RESULT_HANDLED; 416 417 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) { 418 Client *client; 419 EntryGroupInfo *i; 420 static const DBusObjectPathVTable vtable = { 421 NULL, 422 avahi_dbus_msg_entry_group_impl, 423 NULL, 424 NULL, 425 NULL, 426 NULL 427 }; 428 429 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { 430 avahi_log_warn("Error parsing Server::EntryGroupNew message"); 431 goto fail; 432 } 433 434 if (disable_user_service_publishing) 435 return avahi_dbus_respond_error(c, m, AVAHI_ERR_NOT_PERMITTED, NULL); 436 437 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { 438 avahi_log_warn("Too many clients, client request failed."); 439 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL); 440 } 441 442 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) { 443 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name); 444 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); 445 } 446 447 i = avahi_new(EntryGroupInfo, 1); 448 i->id = ++client->current_id; 449 i->client = client; 450 i->path = NULL; 451 i->n_entries = 0; 452 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i); 453 client->n_objects++; 454 455 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, avahi_dbus_entry_group_callback, i))) { 456 avahi_dbus_entry_group_free(i); 457 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 458 } 459 460 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id); 461 dbus_connection_register_object_path(c, i->path, &vtable, i); 462 return avahi_dbus_respond_path(c, m, i->path); 463 464 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) { 465 Client *client; 466 int32_t interface, protocol, aprotocol; 467 uint32_t flags; 468 char *name; 469 SyncHostNameResolverInfo *i; 470 471 if (!dbus_message_get_args( 472 m, &error, 473 DBUS_TYPE_INT32, &interface, 474 DBUS_TYPE_INT32, &protocol, 475 DBUS_TYPE_STRING, &name, 476 DBUS_TYPE_INT32, &aprotocol, 477 DBUS_TYPE_UINT32, &flags, 478 DBUS_TYPE_INVALID) || !name) { 479 avahi_log_warn("Error parsing Server::ResolveHostName message"); 480 goto fail; 481 } 482 483 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { 484 avahi_log_warn("Too many clients, client request failed."); 485 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL); 486 } 487 488 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) { 489 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name); 490 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); 491 } 492 493 i = avahi_new(SyncHostNameResolverInfo, 1); 494 i->client = client; 495 i->message = dbus_message_ref(m); 496 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i); 497 client->n_objects++; 498 499 if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, avahi_dbus_sync_host_name_resolver_callback, i))) { 500 avahi_dbus_sync_host_name_resolver_free(i); 501 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 502 } 503 504 return DBUS_HANDLER_RESULT_HANDLED; 505 506 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) { 507 Client *client; 508 int32_t interface, protocol; 509 uint32_t flags; 510 char *address; 511 SyncAddressResolverInfo *i; 512 AvahiAddress a; 513 514 if (!dbus_message_get_args( 515 m, &error, 516 DBUS_TYPE_INT32, &interface, 517 DBUS_TYPE_INT32, &protocol, 518 DBUS_TYPE_STRING, &address, 519 DBUS_TYPE_UINT32, &flags, 520 DBUS_TYPE_INVALID) || !address) { 521 avahi_log_warn("Error parsing Server::ResolveAddress message"); 522 goto fail; 523 } 524 525 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)) 526 return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL); 527 528 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { 529 avahi_log_warn("Too many clients, client request failed."); 530 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL); 531 } 532 533 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) { 534 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name); 535 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); 536 } 537 538 i = avahi_new(SyncAddressResolverInfo, 1); 539 i->client = client; 540 i->message = dbus_message_ref(m); 541 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i); 542 client->n_objects++; 543 544 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, avahi_dbus_sync_address_resolver_callback, i))) { 545 avahi_dbus_sync_address_resolver_free(i); 546 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 547 } 548 549 return DBUS_HANDLER_RESULT_HANDLED; 550 551 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) { 552 Client *client; 553 DomainBrowserInfo *i; 554 static const DBusObjectPathVTable vtable = { 555 NULL, 556 avahi_dbus_msg_domain_browser_impl, 557 NULL, 558 NULL, 559 NULL, 560 NULL 561 }; 562 int32_t interface, protocol, type; 563 uint32_t flags; 564 char *domain; 565 566 if (!dbus_message_get_args( 567 m, &error, 568 DBUS_TYPE_INT32, &interface, 569 DBUS_TYPE_INT32, &protocol, 570 DBUS_TYPE_STRING, &domain, 571 DBUS_TYPE_INT32, &type, 572 DBUS_TYPE_UINT32, &flags, 573 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) { 574 avahi_log_warn("Error parsing Server::DomainBrowserNew message"); 575 goto fail; 576 } 577 578 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { 579 avahi_log_warn("Too many clients, client request failed."); 580 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL); 581 } 582 583 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) { 584 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name); 585 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); 586 } 587 588 if (!*domain) 589 domain = NULL; 590 591 i = avahi_new(DomainBrowserInfo, 1); 592 i->id = ++client->current_id; 593 i->client = client; 594 i->path = NULL; 595 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i); 596 client->n_objects++; 597 598 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, avahi_dbus_domain_browser_callback, i))) { 599 avahi_dbus_domain_browser_free(i); 600 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 601 } 602 603 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id); 604 dbus_connection_register_object_path(c, i->path, &vtable, i); 605 return avahi_dbus_respond_path(c, m, i->path); 606 607 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) { 608 Client *client; 609 ServiceTypeBrowserInfo *i; 610 static const DBusObjectPathVTable vtable = { 611 NULL, 612 avahi_dbus_msg_service_type_browser_impl, 613 NULL, 614 NULL, 615 NULL, 616 NULL 617 }; 618 int32_t interface, protocol; 619 uint32_t flags; 620 char *domain; 621 622 if (!dbus_message_get_args( 623 m, &error, 624 DBUS_TYPE_INT32, &interface, 625 DBUS_TYPE_INT32, &protocol, 626 DBUS_TYPE_STRING, &domain, 627 DBUS_TYPE_UINT32, &flags, 628 DBUS_TYPE_INVALID)) { 629 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message"); 630 goto fail; 631 } 632 633 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { 634 avahi_log_warn("Too many clients, client request failed."); 635 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL); 636 } 637 638 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) { 639 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name); 640 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); 641 } 642 643 if (!*domain) 644 domain = NULL; 645 646 i = avahi_new(ServiceTypeBrowserInfo, 1); 647 i->id = ++client->current_id; 648 i->client = client; 649 i->path = NULL; 650 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i); 651 client->n_objects++; 652 653 if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiLookupFlags) flags, avahi_dbus_service_type_browser_callback, i))) { 654 avahi_dbus_service_type_browser_free(i); 655 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 656 } 657 658 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id); 659 dbus_connection_register_object_path(c, i->path, &vtable, i); 660 return avahi_dbus_respond_path(c, m, i->path); 661 662 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) { 663 Client *client; 664 ServiceBrowserInfo *i; 665 static const DBusObjectPathVTable vtable = { 666 NULL, 667 avahi_dbus_msg_service_browser_impl, 668 NULL, 669 NULL, 670 NULL, 671 NULL 672 }; 673 int32_t interface, protocol; 674 uint32_t flags; 675 char *domain, *type; 676 677 if (!dbus_message_get_args( 678 m, &error, 679 DBUS_TYPE_INT32, &interface, 680 DBUS_TYPE_INT32, &protocol, 681 DBUS_TYPE_STRING, &type, 682 DBUS_TYPE_STRING, &domain, 683 DBUS_TYPE_UINT32, &flags, 684 DBUS_TYPE_INVALID) || !type) { 685 avahi_log_warn("Error parsing Server::ServiceBrowserNew message"); 686 goto fail; 687 } 688 689 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { 690 avahi_log_warn("Too many clients, client request failed."); 691 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL); 692 } 693 694 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) { 695 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name); 696 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); 697 } 698 699 if (!*domain) 700 domain = NULL; 701 702 i = avahi_new(ServiceBrowserInfo, 1); 703 i->id = ++client->current_id; 704 i->client = client; 705 i->path = NULL; 706 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i); 707 client->n_objects++; 708 709 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, avahi_dbus_service_browser_callback, i))) { 710 avahi_dbus_service_browser_free(i); 711 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 712 } 713 714 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id); 715 dbus_connection_register_object_path(c, i->path, &vtable, i); 716 return avahi_dbus_respond_path(c, m, i->path); 717 718 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) { 719 Client *client; 720 int32_t interface, protocol, aprotocol; 721 uint32_t flags; 722 char *name, *type, *domain; 723 SyncServiceResolverInfo *i; 724 725 if (!dbus_message_get_args( 726 m, &error, 727 DBUS_TYPE_INT32, &interface, 728 DBUS_TYPE_INT32, &protocol, 729 DBUS_TYPE_STRING, &name, 730 DBUS_TYPE_STRING, &type, 731 DBUS_TYPE_STRING, &domain, 732 DBUS_TYPE_INT32, &aprotocol, 733 DBUS_TYPE_UINT32, &flags, 734 DBUS_TYPE_INVALID) || !type) { 735 avahi_log_warn("Error parsing Server::ResolveService message"); 736 goto fail; 737 } 738 739 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { 740 avahi_log_warn("Too many clients, client request failed."); 741 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL); 742 } 743 744 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) { 745 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name); 746 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); 747 } 748 749 if (!*domain) 750 domain = NULL; 751 752 if (!*name) 753 name = NULL; 754 755 i = avahi_new(SyncServiceResolverInfo, 1); 756 i->client = client; 757 i->message = dbus_message_ref(m); 758 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i); 759 client->n_objects++; 760 761 if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, avahi_dbus_sync_service_resolver_callback, i))) { 762 avahi_dbus_sync_service_resolver_free(i); 763 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 764 } 765 766 return DBUS_HANDLER_RESULT_HANDLED; 767 768 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) { 769 Client *client; 770 int32_t interface, protocol, aprotocol; 771 uint32_t flags; 772 char *name, *type, *domain; 773 AsyncServiceResolverInfo *i; 774 static const DBusObjectPathVTable vtable = { 775 NULL, 776 avahi_dbus_msg_async_service_resolver_impl, 777 NULL, 778 NULL, 779 NULL, 780 NULL 781 }; 782 783 if (!dbus_message_get_args( 784 m, &error, 785 DBUS_TYPE_INT32, &interface, 786 DBUS_TYPE_INT32, &protocol, 787 DBUS_TYPE_STRING, &name, 788 DBUS_TYPE_STRING, &type, 789 DBUS_TYPE_STRING, &domain, 790 DBUS_TYPE_INT32, &aprotocol, 791 DBUS_TYPE_UINT32, &flags, 792 DBUS_TYPE_INVALID) || !type) { 793 avahi_log_warn("Error parsing Server::ServiceResolverNew message"); 794 goto fail; 795 } 796 797 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { 798 avahi_log_warn(__FILE__": Too many clients, client request failed."); 799 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL); 800 } 801 802 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) { 803 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name); 804 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); 805 } 806 807 if (!*domain) 808 domain = NULL; 809 810 if (!*name) 811 name = NULL; 812 813 i = avahi_new(AsyncServiceResolverInfo, 1); 814 i->id = ++client->current_id; 815 i->client = client; 816 i->path = NULL; 817 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i); 818 client->n_objects++; 819 820 if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, avahi_dbus_async_service_resolver_callback, i))) { 821 avahi_dbus_async_service_resolver_free(i); 822 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 823 } 824 825/* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */ 826 827 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id); 828 dbus_connection_register_object_path(c, i->path, &vtable, i); 829 return avahi_dbus_respond_path(c, m, i->path); 830 831 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) { 832 Client *client; 833 int32_t interface, protocol, aprotocol; 834 uint32_t flags; 835 char *name; 836 AsyncHostNameResolverInfo *i; 837 static const DBusObjectPathVTable vtable = { 838 NULL, 839 avahi_dbus_msg_async_host_name_resolver_impl, 840 NULL, 841 NULL, 842 NULL, 843 NULL 844 }; 845 846 if (!dbus_message_get_args( 847 m, &error, 848 DBUS_TYPE_INT32, &interface, 849 DBUS_TYPE_INT32, &protocol, 850 DBUS_TYPE_STRING, &name, 851 DBUS_TYPE_INT32, &aprotocol, 852 DBUS_TYPE_UINT32, &flags, 853 DBUS_TYPE_INVALID) || !name) { 854 avahi_log_warn("Error parsing Server::HostNameResolverNew message"); 855 goto fail; 856 } 857 858 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { 859 avahi_log_warn(__FILE__": Too many clients, client request failed."); 860 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL); 861 } 862 863 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) { 864 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name); 865 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); 866 } 867 868 i = avahi_new(AsyncHostNameResolverInfo, 1); 869 i->id = ++client->current_id; 870 i->client = client; 871 i->path = NULL; 872 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i); 873 client->n_objects++; 874 875 if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, aprotocol, (AvahiLookupFlags) flags, avahi_dbus_async_host_name_resolver_callback, i))) { 876 avahi_dbus_async_host_name_resolver_free(i); 877 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 878 } 879 880 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id); 881 dbus_connection_register_object_path(c, i->path, &vtable, i); 882 return avahi_dbus_respond_path(c, m, i->path); 883 884 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) { 885 Client *client; 886 int32_t interface, protocol; 887 uint32_t flags; 888 char *address; 889 AsyncAddressResolverInfo *i; 890 AvahiAddress a; 891 static const DBusObjectPathVTable vtable = { 892 NULL, 893 avahi_dbus_msg_async_address_resolver_impl, 894 NULL, 895 NULL, 896 NULL, 897 NULL 898 }; 899 900 if (!dbus_message_get_args( 901 m, &error, 902 DBUS_TYPE_INT32, &interface, 903 DBUS_TYPE_INT32, &protocol, 904 DBUS_TYPE_STRING, &address, 905 DBUS_TYPE_UINT32, &flags, 906 DBUS_TYPE_INVALID) || !address) { 907 avahi_log_warn("Error parsing Server::AddressResolverNew message"); 908 goto fail; 909 } 910 911 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)) 912 return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL); 913 914 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { 915 avahi_log_warn(__FILE__": Too many clients, client request failed."); 916 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL); 917 } 918 919 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) { 920 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name); 921 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); 922 } 923 924 i = avahi_new(AsyncAddressResolverInfo, 1); 925 i->id = ++client->current_id; 926 i->client = client; 927 i->path = NULL; 928 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i); 929 client->n_objects++; 930 931 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, avahi_dbus_async_address_resolver_callback, i))) { 932 avahi_dbus_async_address_resolver_free(i); 933 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 934 } 935 936 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id); 937 dbus_connection_register_object_path(c, i->path, &vtable, i); 938 return avahi_dbus_respond_path(c, m, i->path); 939 940 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "RecordBrowserNew")) { 941 Client *client; 942 RecordBrowserInfo *i; 943 static const DBusObjectPathVTable vtable = { 944 NULL, 945 avahi_dbus_msg_record_browser_impl, 946 NULL, 947 NULL, 948 NULL, 949 NULL 950 }; 951 int32_t interface, protocol; 952 uint32_t flags; 953 char *name; 954 uint16_t type, clazz; 955 AvahiKey *key; 956 957 if (!dbus_message_get_args( 958 m, &error, 959 DBUS_TYPE_INT32, &interface, 960 DBUS_TYPE_INT32, &protocol, 961 DBUS_TYPE_STRING, &name, 962 DBUS_TYPE_UINT16, &clazz, 963 DBUS_TYPE_UINT16, &type, 964 DBUS_TYPE_UINT32, &flags, 965 DBUS_TYPE_INVALID) || !name) { 966 avahi_log_warn("Error parsing Server::RecordBrowserNew message"); 967 goto fail; 968 } 969 970 if (!avahi_is_valid_domain_name(name)) 971 return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_DOMAIN_NAME, NULL); 972 973 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { 974 avahi_log_warn("Too many clients, client request failed."); 975 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL); 976 } 977 978 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) { 979 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name); 980 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); 981 } 982 983 i = avahi_new(RecordBrowserInfo, 1); 984 i->id = ++client->current_id; 985 i->client = client; 986 i->path = NULL; 987 AVAHI_LLIST_PREPEND(RecordBrowserInfo, record_browsers, client->record_browsers, i); 988 client->n_objects++; 989 990 key = avahi_key_new(name, clazz, type); 991 assert(key); 992 993 if (!(i->record_browser = avahi_s_record_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, key, (AvahiLookupFlags) flags, avahi_dbus_record_browser_callback, i))) { 994 avahi_key_unref(key); 995 avahi_dbus_record_browser_free(i); 996 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 997 } 998 999 avahi_key_unref(key); 1000 1001 i->path = avahi_strdup_printf("/Client%u/RecordBrowser%u", client->id, i->id); 1002 dbus_connection_register_object_path(c, i->path, &vtable, i); 1003 return avahi_dbus_respond_path(c, m, i->path); 1004 } 1005 1006 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m)); 1007 1008fail: 1009 if (dbus_error_is_set(&error)) 1010 dbus_error_free(&error); 1011 1012 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 1013} 1014 1015void dbus_protocol_server_state_changed(AvahiServerState state) { 1016 DBusMessage *m; 1017 int32_t t; 1018 const char *e; 1019 1020 if (!server || !server->bus) 1021 return; 1022 1023 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged"); 1024 t = (int32_t) state; 1025 1026 if (state == AVAHI_SERVER_COLLISION) 1027 e = AVAHI_DBUS_ERR_COLLISION; 1028 else if (state == AVAHI_SERVER_FAILURE) 1029 e = avahi_error_number_to_dbus(avahi_server_errno(avahi_server)); 1030 else 1031 e = AVAHI_DBUS_ERR_OK; 1032 1033 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_STRING, &e, DBUS_TYPE_INVALID); 1034 dbus_connection_send(server->bus, m, NULL); 1035 dbus_message_unref(m); 1036} 1037 1038static int dbus_connect(void) { 1039 DBusError error; 1040 1041 static const DBusObjectPathVTable server_vtable = { 1042 NULL, 1043 msg_server_impl, 1044 NULL, 1045 NULL, 1046 NULL, 1047 NULL 1048 }; 1049 1050 assert(server); 1051 assert(!server->bus); 1052 1053 dbus_error_init(&error); 1054 1055#ifdef HAVE_DBUS_BUS_GET_PRIVATE 1056 if (!(server->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error))) { 1057 assert(dbus_error_is_set(&error)); 1058 avahi_log_error("dbus_bus_get_private(): %s", error.message); 1059 goto fail; 1060 } 1061#else 1062 { 1063 const char *a; 1064 1065 if (!(a = getenv("DBUS_SYSTEM_BUS_ADDRESS")) || !*a) 1066 a = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS; 1067 1068 if (!(server->bus = dbus_connection_open_private(a, &error))) { 1069 assert(dbus_error_is_set(&error)); 1070 avahi_log_error("dbus_bus_open_private(): %s", error.message); 1071 goto fail; 1072 } 1073 1074 if (!dbus_bus_register(server->bus, &error)) { 1075 assert(dbus_error_is_set(&error)); 1076 avahi_log_error("dbus_bus_register(): %s", error.message); 1077 goto fail; 1078 } 1079 } 1080#endif 1081 1082 if (avahi_dbus_connection_glue(server->bus, server->poll_api) < 0) { 1083 avahi_log_error("avahi_dbus_connection_glue() failed"); 1084 goto fail; 1085 } 1086 1087 dbus_connection_set_exit_on_disconnect(server->bus, FALSE); 1088 1089 if (dbus_bus_request_name( 1090 server->bus, 1091 AVAHI_DBUS_NAME, 1092#if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR < 60) 1093 DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, 1094#else 1095 DBUS_NAME_FLAG_DO_NOT_QUEUE, 1096#endif 1097 &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { 1098 if (dbus_error_is_set(&error)) { 1099 avahi_log_error("dbus_bus_request_name(): %s", error.message); 1100 goto fail; 1101 } 1102 1103 avahi_log_error("Failed to acquire D-Bus name '"AVAHI_DBUS_NAME"'"); 1104 goto fail; 1105 } 1106 1107 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) server->poll_api, NULL))) { 1108 avahi_log_error("dbus_connection_add_filter() failed"); 1109 goto fail; 1110 } 1111 1112 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error); 1113 1114 if (dbus_error_is_set(&error)) { 1115 avahi_log_error("dbus_bus_add_match(): %s", error.message); 1116 goto fail; 1117 } 1118 1119 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) { 1120 avahi_log_error("dbus_connection_register_object_path() failed"); 1121 goto fail; 1122 } 1123 1124 return 0; 1125fail: 1126 1127 if (dbus_error_is_set(&error)) 1128 dbus_error_free(&error); 1129 1130 if (server->bus) { 1131#ifdef HAVE_DBUS_CONNECTION_CLOSE 1132 dbus_connection_close(server->bus); 1133#else 1134 dbus_connection_disconnect(server->bus); 1135#endif 1136 dbus_connection_unref(server->bus); 1137 server->bus = NULL; 1138 } 1139 1140 return -1; 1141} 1142 1143static void dbus_disconnect(void) { 1144 assert(server); 1145 1146 while (server->clients) 1147 client_free(server->clients); 1148 1149 assert(server->n_clients == 0); 1150 1151 if (server->bus) { 1152#ifdef HAVE_DBUS_CONNECTION_CLOSE 1153 dbus_connection_close(server->bus); 1154#else 1155 dbus_connection_disconnect(server->bus); 1156#endif 1157 dbus_connection_unref(server->bus); 1158 server->bus = NULL; 1159 } 1160} 1161 1162int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_publishing, int force) { 1163 1164 disable_user_service_publishing = _disable_user_service_publishing; 1165 1166 server = avahi_new(Server, 1); 1167 AVAHI_LLIST_HEAD_INIT(Clients, server->clients); 1168 server->current_id = 0; 1169 server->n_clients = 0; 1170 server->bus = NULL; 1171 server->poll_api = poll_api; 1172 server->reconnect_timeout = NULL; 1173 server->reconnect = force; 1174 1175 if (dbus_connect() < 0) { 1176 struct timeval tv; 1177 1178 if (!force) 1179 goto fail; 1180 1181 avahi_log_warn("WARNING: Failed to contact D-Bus daemon, retrying in %ims.", RECONNECT_MSEC); 1182 1183 avahi_elapse_time(&tv, RECONNECT_MSEC, 0); 1184 server->reconnect_timeout = server->poll_api->timeout_new(server->poll_api, &tv, reconnect_callback, NULL); 1185 } 1186 1187 return 0; 1188 1189fail: 1190 if (server->bus) { 1191#ifdef HAVE_DBUS_CONNECTION_CLOSE 1192 dbus_connection_close(server->bus); 1193#else 1194 dbus_connection_disconnect(server->bus); 1195#endif 1196 1197 dbus_connection_unref(server->bus); 1198 } 1199 1200 avahi_free(server); 1201 server = NULL; 1202 return -1; 1203} 1204 1205void dbus_protocol_shutdown(void) { 1206 1207 if (server) { 1208 dbus_disconnect(); 1209 1210 if (server->reconnect_timeout) 1211 server->poll_api->timeout_free(server->reconnect_timeout); 1212 1213 avahi_free(server); 1214 server = NULL; 1215 } 1216} 1217