X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-daemon%2Fstatic-services.c;h=b9a852cc362b0e685ba8d075c4d46d52c95b8296;hb=f16fb5b323ef49cec531a817a66c88503c32fc46;hp=e459bbca051467616c2775cc9855f9f4cf4a6baf;hpb=2c453196ee040e17e357f3431b0647391c88d616;p=catta diff --git a/avahi-daemon/static-services.c b/avahi-daemon/static-services.c index e459bbc..b9a852c 100644 --- a/avahi-daemon/static-services.c +++ b/avahi-daemon/static-services.c @@ -55,6 +55,8 @@ struct StaticService { uint16_t port; int protocol; + AvahiStringList *subtypes; + AvahiStringList *txt_records; AVAHI_LLIST_FIELDS(StaticService, services); @@ -117,6 +119,7 @@ static StaticService *static_service_new(StaticServiceGroup *group) { s->protocol = AVAHI_PROTO_UNSPEC; s->txt_records = NULL; + s->subtypes = NULL; AVAHI_LLIST_PREPEND(StaticService, services, group->services, s); @@ -150,6 +153,7 @@ static void static_service_free(StaticService *s) { avahi_free(s->domain_name); avahi_string_list_free(s->txt_records); + avahi_string_list_free(s->subtypes); avahi_free(s); } @@ -171,26 +175,42 @@ static void static_service_group_free(StaticServiceGroup *g) { avahi_free(g); } -static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *eg, AvahiEntryGroupState state, void* userdata) { +static void entry_group_callback(AvahiServer *s, AVAHI_GCC_UNUSED AvahiSEntryGroup *eg, AvahiEntryGroupState state, void* userdata) { StaticServiceGroup *g = userdata; assert(s); assert(g); - - if (state == AVAHI_ENTRY_GROUP_COLLISION) { - char *n; - - remove_static_service_group_from_server(g); - n = avahi_alternative_service_name(g->chosen_name); - avahi_free(g->chosen_name); - g->chosen_name = n; + switch (state) { + + case AVAHI_ENTRY_GROUP_COLLISION: { + char *n; + + remove_static_service_group_from_server(g); + + n = avahi_alternative_service_name(g->chosen_name); + avahi_free(g->chosen_name); + g->chosen_name = n; + + avahi_log_notice("Service name conflict for \"%s\" (%s), retrying with \"%s\".", g->name, g->filename, g->chosen_name); + + add_static_service_group_to_server(g); + break; + } + + case AVAHI_ENTRY_GROUP_ESTABLISHED: + avahi_log_info("Service \"%s\" (%s) successfully established.", g->chosen_name, g->filename); + break; - avahi_log_notice("Service name conflict for \"%s\" (%s), retrying with \"%s\".", g->name, g->filename, g->chosen_name); + case AVAHI_ENTRY_GROUP_FAILURE: + avahi_log_warn("Failed to publish service \"%s\" (%s): %s", g->chosen_name, g->filename, avahi_strerror(avahi_server_errno(s))); + remove_static_service_group_from_server(g); + break; - add_static_service_group_to_server(g); - } else if (state == AVAHI_ENTRY_GROUP_ESTABLISHED) - avahi_log_info("Service \"%s\" (%s) successfully established.", g->chosen_name, g->filename); + case AVAHI_ENTRY_GROUP_UNCOMMITED: + case AVAHI_ENTRY_GROUP_REGISTERING: + ; + } } static void add_static_service_group_to_server(StaticServiceGroup *g) { @@ -202,7 +222,9 @@ static void add_static_service_group_to_server(StaticServiceGroup *g) { /* This service group is already registered in the server */ return; - if (!g->chosen_name) { + if (!g->chosen_name || (g->replace_wildcards && strstr(g->name, "%h"))) { + + avahi_free(g->chosen_name); if (g->replace_wildcards) g->chosen_name = replacestr(g->name, "%h", avahi_server_get_host_name(avahi_server)); @@ -217,13 +239,15 @@ static void add_static_service_group_to_server(StaticServiceGroup *g) { assert(avahi_s_entry_group_is_empty(g->entry_group)); for (s = g->services; s; s = s->services_next) { + AvahiStringList *i; if (avahi_server_add_service_strlst( avahi_server, g->entry_group, - -1, s->protocol, - g->chosen_name, s->type, - s->domain_name, s->host_name, s->port, + AVAHI_IF_UNSPEC, s->protocol, + 0, + g->chosen_name, s->type, s->domain_name, + s->host_name, s->port, s->txt_records) < 0) { avahi_log_error("Failed to add service '%s' of type '%s', ignoring service group (%s): %s", g->chosen_name, s->type, g->filename, @@ -231,6 +255,22 @@ static void add_static_service_group_to_server(StaticServiceGroup *g) { remove_static_service_group_from_server(g); return; } + + for (i = s->subtypes; i; i = i->next) { + + if (avahi_server_add_service_subtype( + avahi_server, + g->entry_group, + AVAHI_IF_UNSPEC, s->protocol, + 0, + g->chosen_name, s->type, s->domain_name, + (char*) i->text) < 0) { + + avahi_log_error("Failed to add subtype '%s' for service '%s' of type '%s', ignoring subtype (%s): %s", + i->text, g->chosen_name, s->type, g->filename, + avahi_strerror(avahi_server_errno(avahi_server))); + } + } } avahi_s_entry_group_commit(g->entry_group); @@ -249,6 +289,7 @@ typedef enum { XML_TAG_NAME, XML_TAG_SERVICE, XML_TAG_TYPE, + XML_TAG_SUBTYPE, XML_TAG_DOMAIN_NAME, XML_TAG_HOST_NAME, XML_TAG_PORT, @@ -263,6 +304,10 @@ struct xml_userdata { char *buf; }; +#ifndef XMLCALL +#define XMLCALL +#endif + static void XMLCALL xml_start(void *data, const char *el, const char *attr[]) { struct xml_userdata *u = data; @@ -325,6 +370,11 @@ static void XMLCALL xml_start(void *data, const char *el, const char *attr[]) { goto invalid_attr; u->current_tag = XML_TAG_TYPE; + } else if (u->current_tag == XML_TAG_SERVICE && strcmp(el, "subtype") == 0) { + if (attr[0]) + goto invalid_attr; + + u->current_tag = XML_TAG_SUBTYPE; } else if (u->current_tag == XML_TAG_SERVICE && strcmp(el, "domain-name") == 0) { if (attr[0]) goto invalid_attr; @@ -358,7 +408,7 @@ invalid_attr: return; } -static void XMLCALL xml_end(void *data, const char *el) { +static void XMLCALL xml_end(void *data, AVAHI_GCC_UNUSED const char *el) { struct xml_userdata *u = data; assert(u); @@ -418,6 +468,14 @@ static void XMLCALL xml_end(void *data, const char *el) { u->current_tag = XML_TAG_SERVICE; break; } + + case XML_TAG_SUBTYPE: { + assert(u->service); + + u->service->subtypes = avahi_string_list_add(u->service->subtypes, u->buf ? u->buf : ""); + u->current_tag = XML_TAG_SERVICE; + break; + } case XML_TAG_TYPE: case XML_TAG_DOMAIN_NAME: @@ -481,6 +539,7 @@ static void XMLCALL xml_cdata(void *data, const XML_Char *s, int len) { case XML_TAG_PORT: case XML_TAG_TXT_RECORD: + case XML_TAG_SUBTYPE: assert(u->service); u->buf = append_cdata(u->buf, s, len); break; @@ -556,7 +615,7 @@ static int static_service_group_load(StaticServiceGroup *g) { } if (!XML_ParseBuffer(parser, n, n == 0)) { - avahi_log_error("XML_ParseBuffer() failed at line %d: %s.\n", XML_GetCurrentLineNumber(parser), XML_ErrorString(XML_GetErrorCode(parser))); + avahi_log_error("XML_ParseBuffer() failed at line %d: %s.\n", (int) XML_GetCurrentLineNumber(parser), XML_ErrorString(XML_GetErrorCode(parser))); goto finish; } @@ -595,9 +654,10 @@ static void load_file(char *n) { } } -void static_service_load(void) { +void static_service_load(int in_chroot) { StaticServiceGroup *g, *n; glob_t globbuf; + int globret; char **p; for (g = groups; g; g = n) { @@ -624,8 +684,25 @@ void static_service_load(void) { } memset(&globbuf, 0, sizeof(globbuf)); - if (glob(AVAHI_SERVICE_DIR "/*.service", GLOB_ERR, NULL, &globbuf) != 0) - avahi_log_error("Failed to read service directory."); + + if ((globret = glob(in_chroot ? "/services/*.service" : AVAHI_SERVICE_DIR "/*.service", GLOB_ERR, NULL, &globbuf)) != 0) + + switch (globret) { +#ifdef GLOB_NOSPACE + case GLOB_NOSPACE: + avahi_log_error("Not enough memory to read service directory "AVAHI_SERVICE_DIR"."); + break; +#endif +#ifdef GLOB_NOMATCH + case GLOB_NOMATCH: + avahi_log_info("No service file found in "AVAHI_SERVICE_DIR"."); + break; +#endif + default: + avahi_log_error("Failed to read "AVAHI_SERVICE_DIR"."); + break; + } + else { for (p = globbuf.gl_pathv; *p; p++) load_file(*p);