/* Can be used in either PA or Avahi mainloop context since the bits of u->core
 * that we access don't change after startup. */
static AvahiStringList* txt_record_server_data(pa_core *c, AvahiStringList *l) {
    char s[128];
    char *t;

    pa_assert(c);

    l = avahi_string_list_add_pair(l, "server-version", PACKAGE_NAME" "PACKAGE_VERSION);

    t = pa_get_user_name_malloc();
    l = avahi_string_list_add_pair(l, "user-name", t);
    pa_xfree(t);

    t = pa_machine_id();
    l = avahi_string_list_add_pair(l, "machine-id", t);
    pa_xfree(t);

    t = pa_uname_string();
    l = avahi_string_list_add_pair(l, "uname", t);
    pa_xfree(t);

    l = avahi_string_list_add_pair(l, "fqdn", pa_get_fqdn(s, sizeof(s)));
    l = avahi_string_list_add_printf(l, "cookie=0x%08x", c->cookie);

    return l;
}
AvahiStringList*
Avahi::PresencePublisher::prepare_txt_record ()
{
  AvahiStringList* result = NULL;

  result = avahi_string_list_add_printf (result,
					 "presence=%s",
					 details.get_presence ().c_str ());
  result = avahi_string_list_add_printf (result,
					 "status=%s",
					 details.get_status ().c_str ());
  result = avahi_string_list_add_printf (result,
					 "software=%s %s",
					 PACKAGE_NAME, PACKAGE_VERSION);

  return result;
}
static AvahiStringList *add_magic_cookie(
    AvahiServer *s,
    AvahiStringList *strlst) {

    assert(s);

    if (!s->config.add_service_cookie)
        return strlst;

    if (avahi_string_list_find(strlst, AVAHI_SERVICE_COOKIE))
        /* This string list already contains a magic cookie */
        return strlst;

    return avahi_string_list_add_printf(strlst, AVAHI_SERVICE_COOKIE"=%u", s->local_service_cookie);
}
Example #4
0
static cupsd_txt_t			/* O - TXT record */
dnssdBuildTxtRecord(
    cupsd_printer_t *p,			/* I - Printer information */
    int             for_lpd)		/* I - 1 = LPD, 0 = IPP */
{
  int		i,			/* Looping var */
		count;			/* Count of key/value pairs */
  char		admin_hostname[256],	/* .local hostname for admin page */
		adminurl_str[256],	/* URL for the admin page */
		type_str[32],		/* Type to string buffer */
		state_str[32],		/* State to string buffer */
		rp_str[1024],		/* Queue name string buffer */
		air_str[1024],		/* auth-info-required string buffer */
		*keyvalue[32][2];	/* Table of key/value pairs */
  cupsd_txt_t	txt;			/* TXT record */


 /*
  * Load up the key value pairs...
  */

  count = 0;

  if (!for_lpd || (BrowseLocalProtocols & BROWSE_LPD))
  {
    keyvalue[count  ][0] = "txtvers";
    keyvalue[count++][1] = "1";

    keyvalue[count  ][0] = "qtotal";
    keyvalue[count++][1] = "1";

    keyvalue[count  ][0] = "rp";
    keyvalue[count++][1] = rp_str;
    if (for_lpd)
      strlcpy(rp_str, p->name, sizeof(rp_str));
    else
      snprintf(rp_str, sizeof(rp_str), "%s/%s",
	       (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
	       p->name);

    keyvalue[count  ][0] = "ty";
    keyvalue[count++][1] = p->make_model ? p->make_model : "Unknown";

    if (strstr(DNSSDHostName, ".local"))
      strlcpy(admin_hostname, DNSSDHostName, sizeof(admin_hostname));
    else
      snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.",
               DNSSDHostName);
    httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str),
#  ifdef HAVE_SSL
		     "https",
#  else
		     "http",
#  endif /* HAVE_SSL */
		     NULL, admin_hostname, DNSSDPort, "/%s/%s",
		     (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
		     p->name);
    keyvalue[count  ][0] = "adminurl";
    keyvalue[count++][1] = adminurl_str;

    if (p->location)
    {
      keyvalue[count  ][0] = "note";
      keyvalue[count++][1] = p->location;
    }

    keyvalue[count  ][0] = "priority";
    keyvalue[count++][1] = for_lpd ? "100" : "0";

    keyvalue[count  ][0] = "product";
    keyvalue[count++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown";

    keyvalue[count  ][0] = "pdl";
    keyvalue[count++][1] = p->pdl ? p->pdl : "application/postscript";

    if (get_auth_info_required(p, air_str, sizeof(air_str)))
    {
      keyvalue[count  ][0] = "air";
      keyvalue[count++][1] = air_str;
    }

    keyvalue[count  ][0] = "UUID";
    keyvalue[count++][1] = p->uuid + 9;

  #ifdef HAVE_SSL
    keyvalue[count  ][0] = "TLS";
    keyvalue[count++][1] = "1.2";
  #endif /* HAVE_SSL */

    if (p->type & CUPS_PRINTER_FAX)
    {
      keyvalue[count  ][0] = "Fax";
      keyvalue[count++][1] = "T";
      keyvalue[count  ][0] = "rfo";
      keyvalue[count++][1] = rp_str;
    }

    if (p->type & CUPS_PRINTER_COLOR)
    {
      keyvalue[count  ][0] = "Color";
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F";
    }

    if (p->type & CUPS_PRINTER_DUPLEX)
    {
      keyvalue[count  ][0] = "Duplex";
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F";
    }

    if (p->type & CUPS_PRINTER_STAPLE)
    {
      keyvalue[count  ][0] = "Staple";
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F";
    }

    if (p->type & CUPS_PRINTER_COPIES)
    {
      keyvalue[count  ][0] = "Copies";
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F";
    }

    if (p->type & CUPS_PRINTER_COLLATE)
    {
      keyvalue[count  ][0] = "Collate";
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F";
    }

    if (p->type & CUPS_PRINTER_PUNCH)
    {
      keyvalue[count  ][0] = "Punch";
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F";
    }

    if (p->type & CUPS_PRINTER_BIND)
    {
      keyvalue[count  ][0] = "Bind";
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F";
    }

    if (p->type & CUPS_PRINTER_SORT)
    {
      keyvalue[count  ][0] = "Sort";
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F";
    }

    if (p->type & CUPS_PRINTER_MFP)
    {
      keyvalue[count  ][0] = "Scan";
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F";
    }

    snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE);
    snprintf(state_str, sizeof(state_str), "%d", p->state);

    keyvalue[count  ][0] = "printer-state";
    keyvalue[count++][1] = state_str;

    keyvalue[count  ][0] = "printer-type";
    keyvalue[count++][1] = type_str;
  }

 /*
  * Then pack them into a proper txt record...
  */

#  ifdef HAVE_DNSSD
  TXTRecordCreate(&txt, 0, NULL);

  for (i = 0; i < count; i ++)
  {
    size_t len = strlen(keyvalue[i][1]);

    if (len < 256)
      TXTRecordSetValue(&txt, keyvalue[i][0], (uint8_t)len, keyvalue[i][1]);
  }

#  else
  for (i = 0, txt = NULL; i < count; i ++)
    txt = avahi_string_list_add_printf(txt, "%s=%s", keyvalue[i][0],
                                       keyvalue[i][1]);
#  endif /* HAVE_DNSSD */

  return (txt);
}
Example #5
0
int
dnssd_register(AvahiClient *c)
{
  AvahiStringList *ipp_txt;             /* DNS-SD IPP TXT record */
  char            temp[256];            /* Subtype service string */
  char            dnssd_name[1024];
  char            *dev_id = NULL;
  const char      *make;                /* I - Manufacturer */
  const char      *model;               /* I - Model name */
  const char      *serial = NULL;
  const char      *cmd;
  int             pwgraster = 0,
                  appleraster = 0,
                  pclm = 0,
                  pdf = 0,
                  jpeg = 0;
  char            formats[1024];        /* I - Supported formats */
  char            *ptr;
  int             error;

 /*
  * Parse the device ID for MFG, MDL, and CMD
  */

  dev_id = strdup(g_options.device_id);
  if ((ptr = strcasestr(dev_id, "MFG:")) == NULL)
    if ((ptr = strcasestr(dev_id, "MANUFACTURER:")) == NULL) {
      ERR("No manufacturer info in device ID");
      free(dev_id);
      return -1;
    }
  make = strchr(ptr, ':') + 1;
  if ((ptr = strcasestr(dev_id, "MDL:")) == NULL)
    if ((ptr = strcasestr(dev_id, "MODEL:")) == NULL) {
      ERR("No model info in device ID");
      free(dev_id);
      return -1;
    }
  model = strchr(ptr, ':') + 1;
  if ((ptr = strcasestr(dev_id, "SN:")) == NULL)
    if ((ptr = strcasestr(dev_id, "SERN:")) == NULL) {
      if ((ptr = strcasestr(dev_id, "SERIALNUMBER:")) == NULL) {
	NOTE("No serial number info in device ID");
      }
    }
  if (ptr)
    serial = strchr(ptr, ':') + 1;
  if ((ptr = strcasestr(dev_id, "CMD:")) == NULL)
    if ((ptr = strcasestr(dev_id, "COMMAND SET:")) == NULL) {
      ERR("No page description language info in device ID");
      free(dev_id);
      return -1;
    }
  cmd = strchr(ptr, ':') + 1;
  ptr = strchr(make, ';');
  if (ptr) *ptr = '\0';
  ptr = strchr(model, ';');
  if (ptr) *ptr = '\0';
  if (serial) {
    ptr = strchr(serial, ';');
    if (ptr) *ptr = '\0';
  }
  ptr = strchr(cmd, ';');
  if (ptr) *ptr = '\0';

  if ((ptr = strcasestr(cmd, "pwg")) != NULL &&
      (ptr = strcasestr(ptr, "raster")) != NULL)
    pwgraster = 1;
  if (((ptr = strcasestr(cmd, "apple")) != NULL &&
       (ptr = strcasestr(ptr, "raster")) != NULL) ||
      ((ptr = strcasestr(cmd, "urf")) != NULL))
    appleraster = 1;
  if ((ptr = strcasestr(cmd, "pclm")) != NULL)
    pclm = 1;
  if ((ptr = strcasestr(cmd, "pdf")) != NULL)
    pdf = 1;
  if ((ptr = strcasestr(cmd, "jpeg")) != NULL ||
      (ptr = strcasestr(cmd, "jpg")) != NULL)
    jpeg = 1;
  snprintf(formats, sizeof(formats),"%s%s%s%s%s",
	   (pdf ? "application/pdf," : ""),
	   (pwgraster ? "image/pwg-raster," : ""),
	   (appleraster ? "image/urf," : ""),
	   (pclm ? "application/PCLm," : ""),
	   (jpeg ? "image/jpeg," : ""));
  formats[strlen(formats) - 1] = '\0';

 /*
  * Additional printer properties
  */

  snprintf(temp, sizeof(temp), "http://localhost:%d/", g_options.real_port);
  if (serial)
    snprintf(dnssd_name, sizeof(dnssd_name), "%s [%s]", model, serial);
  else
    snprintf(dnssd_name, sizeof(dnssd_name), "%s", model);

 /*
  * Create the TXT record...
  */

  ipp_txt = NULL;
  ipp_txt = avahi_string_list_add_printf(ipp_txt, "rp=ipp/print");
  ipp_txt = avahi_string_list_add_printf(ipp_txt, "ty=%s %s", make, model);
  if (strcasecmp(g_options.interface, "lo") == 0)
    ipp_txt = avahi_string_list_add_printf(ipp_txt, "adminurl=%s", temp);
  ipp_txt = avahi_string_list_add_printf(ipp_txt, "product=(%s)", model);
  ipp_txt = avahi_string_list_add_printf(ipp_txt, "pdl=%s", formats);
  ipp_txt = avahi_string_list_add_printf(ipp_txt, "Color=U");
  ipp_txt = avahi_string_list_add_printf(ipp_txt, "Duplex=U");
  ipp_txt = avahi_string_list_add_printf(ipp_txt, "usb_MFG=%s", make);
  ipp_txt = avahi_string_list_add_printf(ipp_txt, "usb_MDL=%s", model);
  if (appleraster)
    ipp_txt = avahi_string_list_add_printf(ipp_txt, "URF=CP1,IS1-5-7,MT1-2-3-4-5-6-8-9-10-11-12-13,RS300,SRGB24,V1.4,W8,DM1");
  ipp_txt = avahi_string_list_add_printf(ipp_txt, "priority=60");
  ipp_txt = avahi_string_list_add_printf(ipp_txt, "txtvers=1");
  ipp_txt = avahi_string_list_add_printf(ipp_txt, "qtotal=1");
  free(dev_id);

 /*
  * Register _printer._tcp (LPD) with port 0 to reserve the service name...
  */

  NOTE("Registering printer %s on interface %s for DNS-SD broadcasting ...",
       dnssd_name, g_options.interface);

  if (g_options.dnssd_data->ipp_ref == NULL)
    g_options.dnssd_data->ipp_ref =
      avahi_entry_group_new((c ? c : g_options.dnssd_data->DNSSDClient),
			    dnssd_callback, NULL);

  if (g_options.dnssd_data->ipp_ref == NULL) {
    ERR("Could not establish Avahi entry group");
    avahi_string_list_free(ipp_txt);
    return -1;
  }

  error =
    avahi_entry_group_add_service_strlst(g_options.dnssd_data->ipp_ref,
					 (g_options.interface ?
					  (int)if_nametoindex(g_options.interface) :
					  AVAHI_IF_UNSPEC),
					 AVAHI_PROTO_UNSPEC, 0,
					 dnssd_name,
					 "_printer._tcp", NULL, NULL, 0,
					 NULL);
  if (error)
    ERR("Error registering %s as Unix printer (_printer._tcp): %d", dnssd_name,
	error);
  else
    NOTE("Registered %s as Unix printer (_printer._tcp).", dnssd_name);

 /*
  * Then register the _ipp._tcp (IPP)...
  */

  error =
    avahi_entry_group_add_service_strlst(g_options.dnssd_data->ipp_ref,
					 (g_options.interface ?
					  (int)if_nametoindex(g_options.interface) :
					  AVAHI_IF_UNSPEC),
					 AVAHI_PROTO_UNSPEC, 0,
					 dnssd_name,
					 "_ipp._tcp", NULL, NULL, g_options.real_port,
					 ipp_txt);
  if (error)
    ERR("Error registering %s as IPP printer (_ipp._tcp): %d", dnssd_name,
	error);
  else {
    NOTE("Registered %s as IPP printer (_ipp._tcp).", dnssd_name);
    error =
      avahi_entry_group_add_service_subtype(g_options.dnssd_data->ipp_ref,
					    (g_options.interface ?
					     (int)if_nametoindex(g_options.interface) :
					     AVAHI_IF_UNSPEC),
					    AVAHI_PROTO_UNSPEC, 0,
					    dnssd_name,
					    "_ipp._tcp", NULL,
					    (appleraster && !pwgraster ?
					     "_universal._sub._ipp._tcp" :
					     "_print._sub._ipp._tcp"));
    if (error)
      ERR("Error registering subtype for IPP printer %s (_print._sub._ipp._tcp or _universal._sub._ipp._tcp): %d",
	  dnssd_name, error);
    else
      NOTE("Registered subtype for IPP printer %s (_print._sub._ipp._tcp or _universal._sub._ipp._tcp).",
	   dnssd_name);
  }

 /*
  * Finally _http.tcp (HTTP) for the web interface...
  */

  error =
    avahi_entry_group_add_service_strlst(g_options.dnssd_data->ipp_ref,
					 (g_options.interface ?
					  (int)if_nametoindex(g_options.interface) :
					  AVAHI_IF_UNSPEC),
					 AVAHI_PROTO_UNSPEC, 0,
					 dnssd_name,
					 "_http._tcp", NULL, NULL, g_options.real_port,
					 NULL);
  if (error)
    ERR("Error registering web interface of %s (_http._tcp): %d", dnssd_name,
	error);
  else {
    NOTE("Registered web interface of %s (_http._tcp).", dnssd_name);
    error =
      avahi_entry_group_add_service_subtype(g_options.dnssd_data->ipp_ref,
					    (g_options.interface ?
					     (int)if_nametoindex(g_options.interface) :
					     AVAHI_IF_UNSPEC),
					    AVAHI_PROTO_UNSPEC, 0,
					    dnssd_name,
					    "_http._tcp", NULL,
					    "_printer._sub._http._tcp");
    if (error)
      ERR("Error registering subtype for web interface of %s (_printer._sub._http._tcp): %d",
	  dnssd_name, error);
    else
      NOTE("Registered subtype for web interface of %s (_printer._sub._http._tcp).",
	   dnssd_name);
  }

 /*
  * Commit it...
  */

  avahi_entry_group_commit(g_options.dnssd_data->ipp_ref);

  avahi_string_list_free(ipp_txt);

  return 0;
}
Example #6
0
/*
 * This function tries to register the AFP DNS
 * SRV service type.
 */
static void register_stuff(void) {
    uint port;
    const struct vol *volume;
    DSI *dsi;
    char name[MAXINSTANCENAMELEN+1];
    AvahiStringList *strlist = NULL;
    AvahiStringList *strlist2 = NULL;
    char tmpname[256];

    assert(ctx->client);

    if (!ctx->group) {
        if (!(ctx->group = avahi_entry_group_new(ctx->client, publish_reply, ctx))) {
            LOG(log_error, logtype_afpd, "Failed to create entry group: %s",
                avahi_strerror(avahi_client_errno(ctx->client)));
            goto fail;
        }
    }

    if (avahi_entry_group_is_empty(ctx->group)) {
        /* Register our service */

        /* Build AFP volumes list */
        int i = 0;
        strlist = avahi_string_list_add_printf(strlist, "sys=waMa=0,adVF=0x100");

        for (volume = getvolumes(); volume; volume = volume->v_next) {

            if (convert_string(CH_UCS2, CH_UTF8_MAC, volume->v_u8mname, -1, tmpname, 255) <= 0) {
                LOG ( log_error, logtype_afpd, "Could not set Zeroconf volume name for TimeMachine");
                goto fail;
            }

            if (volume->v_flags & AFPVOL_TM) {
                if (volume->v_uuid) {
                    LOG(log_info, logtype_afpd, "Registering volume '%s' with UUID: '%s' for TimeMachine",
                        volume->v_localname, volume->v_uuid);
                    strlist = avahi_string_list_add_printf(strlist, "dk%u=adVN=%s,adVF=0xa1,adVU=%s",
                                                           i++, tmpname, volume->v_uuid);
                } else {
                    LOG(log_warning, logtype_afpd, "Registering volume '%s' for TimeMachine. But UUID is invalid.",
                        volume->v_localname);
                    strlist = avahi_string_list_add_printf(strlist, "dk%u=adVN=%s,adVF=0xa1",
                                                           i++, tmpname);
                }
            }
        }

        /* AFP server */
        for (dsi = ctx->obj->dsi; dsi; dsi = dsi->next) {
            port = getip_port((struct sockaddr *)&dsi->server);

            LOG(log_info, logtype_afpd, "hostname: %s", ctx->obj->options.hostname);

            if (convert_string(ctx->obj->options.unixcharset,
                               CH_UTF8,
                               ctx->obj->options.hostname,
                               -1,
                               name,
                               MAXINSTANCENAMELEN) <= 0) {
                LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name: %s", ctx->obj->options.hostname);
                goto fail;
            }
            if ((dsi->bonjourname = strdup(name)) == NULL) {
                LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name");
                goto fail;

            }
            LOG(log_info, logtype_afpd, "Registering server '%s' with Bonjour",
                dsi->bonjourname);

            if (avahi_entry_group_add_service(ctx->group,
                                              AVAHI_IF_UNSPEC,
                                              AVAHI_PROTO_UNSPEC,
                                              0,
                                              dsi->bonjourname,
                                              AFP_DNS_SERVICE_TYPE,
                                              NULL,
                                              NULL,
                                              port,
                                              NULL) < 0) {
                LOG(log_error, logtype_afpd, "Failed to add service: %s",
                    avahi_strerror(avahi_client_errno(ctx->client)));
                goto fail;
            }

            if (i && avahi_entry_group_add_service_strlst(ctx->group,
                    AVAHI_IF_UNSPEC,
                    AVAHI_PROTO_UNSPEC,
                    0,
                    dsi->bonjourname,
                    ADISK_SERVICE_TYPE,
                    NULL,
                    NULL,
                    9, /* discard */
                    strlist) < 0) {
                LOG(log_error, logtype_afpd, "Failed to add service: %s",
                    avahi_strerror(avahi_client_errno(ctx->client)));
                goto fail;
            }	/* if */

            if (ctx->obj->options.mimicmodel) {
                strlist2 = avahi_string_list_add_printf(strlist2, "model=%s", ctx->obj->options.mimicmodel);
                if (avahi_entry_group_add_service_strlst(ctx->group,
                        AVAHI_IF_UNSPEC,
                        AVAHI_PROTO_UNSPEC,
                        0,
                        dsi->bonjourname,
                        DEV_INFO_SERVICE_TYPE,
                        NULL,
                        NULL,
                        0,
                        strlist2) < 0) {
                    LOG(log_error, logtype_afpd, "Failed to add service: %s",
                        avahi_strerror(avahi_client_errno(ctx->client)));
                    goto fail;
                }
            } /* if (config->obj.options.mimicmodel) */

        }	/* for config*/

        if (avahi_entry_group_commit(ctx->group) < 0) {
            LOG(log_error, logtype_afpd, "Failed to commit entry group: %s",
                avahi_strerror(avahi_client_errno(ctx->client)));
            goto fail;
        }

    }	/* if avahi_entry_group_is_empty*/

    return;

fail:
    time(NULL);
//    avahi_threaded_poll_quit(ctx->threaded_poll);
}
Example #7
0
static void create_services(AvahiClient * c, Game * game)
{
	gchar *hostname;
	gchar *servicename;
	AvahiStringList *sl;
	int ret;

	g_assert(c != NULL);

	/* If this is the first time we're called, let's create a new entry group */
	if (!group) {
		if (!
		    (group =
		     avahi_entry_group_new(c, entry_group_callback,
					   NULL))) {
			log_message(MSG_ERROR, _("Avahi error: %s, %s\n"),
				    "avahi_entry_group_new() failed",
				    avahi_strerror(avahi_client_errno(c)));
			avahi_glib_poll_free(glib_poll);
			return;
		}
	}

	sl = avahi_string_list_new(NULL, NULL);
	sl = avahi_string_list_add_printf(sl, "version=%s",
					  PROTOCOL_VERSION);
	sl = avahi_string_list_add_printf(sl, "title=%s",
					  game->params->title);

	/* Add the service for IPP */
	hostname =
	    game->hostname ? g_strdup(game->hostname) : get_my_hostname();
	servicename =
	    g_strdup_printf("%s [%s]", hostname, game->server_port);
	g_free(hostname);
	ret = avahi_entry_group_add_service_strlst(group,
						   AVAHI_IF_UNSPEC,
						   AVAHI_NETWORK_PROTOCOL,
						   0,
						   servicename,
						   AVAHI_ANNOUNCE_NAME,
						   NULL,
						   NULL,
						   atoi(game->server_port),
						   sl);
	g_free(servicename);
	if (ret < 0) {
		gchar *msg = g_strdup_printf("Failed to add '%s' service",
					     AVAHI_ANNOUNCE_NAME);
		log_message(MSG_ERROR, _("Avahi error: %s, %s\n"), msg,
			    avahi_strerror(ret));
		g_free(msg);
		avahi_string_list_free(sl);
		avahi_glib_poll_free(glib_poll);
		return;
	}

	/* Tell the server to register the service */
	if ((ret = avahi_entry_group_commit(group)) < 0) {
		log_message(MSG_ERROR, _("Avahi error: %s, %s\n"),
			    "Failed to commit entry_group",
			    avahi_strerror(ret));
		avahi_string_list_free(sl);
		avahi_glib_poll_free(glib_poll);
		return;
	}

	avahi_string_list_free(sl);
	return;
}
Example #8
0
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) {
    char *t, *v;
    uint8_t data[1024];
    AvahiStringList *a = NULL, *b, *p;
    size_t size, n;
    int r;

    a = avahi_string_list_new("prefix", "a", "b", NULL);
    
    a = avahi_string_list_add(a, "start");
    a = avahi_string_list_add(a, "foo=99");
    a = avahi_string_list_add(a, "bar");
    a = avahi_string_list_add(a, "");
    a = avahi_string_list_add(a, "");
    a = avahi_string_list_add(a, "quux");
    a = avahi_string_list_add(a, "");
    a = avahi_string_list_add_arbitrary(a, (const uint8_t*) "null\0null", 9);
    a = avahi_string_list_add_printf(a, "seven=%i %c", 7, 'x');
    a = avahi_string_list_add_pair(a, "blubb", "blaa");
    a = avahi_string_list_add_pair(a, "uxknurz", NULL);
    a = avahi_string_list_add_pair_arbitrary(a, "uxknurz2", (const uint8_t*) "blafasel\0oerks", 14);
    
    a = avahi_string_list_add(a, "end");

    t = avahi_string_list_to_string(a);
    printf("--%s--\n", t);
    avahi_free(t);
    
    n = avahi_string_list_serialize(a, NULL, 0);
    size = avahi_string_list_serialize(a, data, sizeof(data));
    assert(size == n);

    printf("%u\n", size);

    for (t = (char*) data, n = 0; n < size; n++, t++) {
        if (*t <= 32)
            printf("(%u)", *t);
        else
            printf("%c", *t);
    }

    printf("\n");
    
    assert(avahi_string_list_parse(data, size, &b) == 0);

    printf("equal: %i\n", avahi_string_list_equal(a, b));
    
    t = avahi_string_list_to_string(b);
    printf("--%s--\n", t);
    avahi_free(t);

    avahi_string_list_free(b);

    b = avahi_string_list_copy(a);

    assert(avahi_string_list_equal(a, b));

    t = avahi_string_list_to_string(b);
    printf("--%s--\n", t);
    avahi_free(t);

    p = avahi_string_list_find(a, "seven");
    assert(p);
    
    r = avahi_string_list_get_pair(p, &t, &v, NULL);  
    assert(r >= 0);
    assert(t);
    assert(v);
    
    printf("<%s>=<%s>\n", t, v);
    avahi_free(t);
    avahi_free(v);

    p = avahi_string_list_find(a, "quux");
    assert(p);

    r = avahi_string_list_get_pair(p, &t, &v, NULL);
    assert(r >= 0);
    assert(t);
    assert(!v);

    printf("<%s>=<%s>\n", t, v);
    avahi_free(t);
    avahi_free(v);
    
    avahi_string_list_free(a);
    avahi_string_list_free(b);

    n = avahi_string_list_serialize(NULL, NULL, 0);
    size = avahi_string_list_serialize(NULL, data, sizeof(data));
    assert(size == 1);
    assert(size == n);

    assert(avahi_string_list_parse(data, size, &a) == 0);
    assert(!a);
    
    return 0;
}
static int publish_service(struct service *s) {
    int r = -1;
    AvahiStringList *txt = NULL;
    const char *name = NULL, *t;
    pa_proplist *proplist = NULL;
    pa_sample_spec ss;
    pa_channel_map map;
    char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
    enum service_subtype subtype;

    const char * const subtype_text[] = {
        [SUBTYPE_HARDWARE] = "hardware",
        [SUBTYPE_VIRTUAL] = "virtual",
        [SUBTYPE_MONITOR] = "monitor"
    };

    pa_assert(s);

    if (!s->userdata->client || avahi_client_get_state(s->userdata->client) != AVAHI_CLIENT_S_RUNNING)
        return 0;

    if (!s->entry_group) {
        if (!(s->entry_group = avahi_entry_group_new(s->userdata->client, service_entry_group_callback, s))) {
            pa_log("avahi_entry_group_new(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
            goto finish;
        }
    } else
        avahi_entry_group_reset(s->entry_group);

    txt = txt_record_server_data(s->userdata->core, txt);

    get_service_data(s, &ss, &map, &name, &proplist, &subtype);
    txt = avahi_string_list_add_pair(txt, "device", name);
    txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate);
    txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels);
    txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format));
    txt = avahi_string_list_add_pair(txt, "channel_map", pa_channel_map_snprint(cm, sizeof(cm), &map));
    txt = avahi_string_list_add_pair(txt, "subtype", subtype_text[subtype]);

    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_DESCRIPTION)))
        txt = avahi_string_list_add_pair(txt, "description", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_ICON_NAME)))
        txt = avahi_string_list_add_pair(txt, "icon-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_VENDOR_NAME)))
        txt = avahi_string_list_add_pair(txt, "vendor-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_PRODUCT_NAME)))
        txt = avahi_string_list_add_pair(txt, "product-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_CLASS)))
        txt = avahi_string_list_add_pair(txt, "class", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_FORM_FACTOR)))
        txt = avahi_string_list_add_pair(txt, "form-factor", t);

    if (avahi_entry_group_add_service_strlst(
                s->entry_group,
                AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                0,
                s->service_name,
                pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
                NULL,
                NULL,
                compute_port(s->userdata),
                txt) < 0) {

        pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    if (avahi_entry_group_add_service_subtype(
                s->entry_group,
                AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                0,
                s->service_name,
                pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
                NULL,
                pa_sink_isinstance(s->device) ? (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SINK_HARDWARE : SERVICE_SUBTYPE_SINK_VIRTUAL) :
                (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SOURCE_HARDWARE : (subtype == SUBTYPE_VIRTUAL ? SERVICE_SUBTYPE_SOURCE_VIRTUAL : SERVICE_SUBTYPE_SOURCE_MONITOR))) < 0) {

        pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    if (pa_source_isinstance(s->device) && subtype != SUBTYPE_MONITOR) {
        if (avahi_entry_group_add_service_subtype(
                    s->entry_group,
                    AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                    0,
                    s->service_name,
                    SERVICE_TYPE_SOURCE,
                    NULL,
                    SERVICE_SUBTYPE_SOURCE_NON_MONITOR) < 0) {

            pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
            goto finish;
        }
    }

    if (avahi_entry_group_commit(s->entry_group) < 0) {
        pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    r = 0;
    pa_log_debug("Successfully created entry group for %s.", s->service_name);

finish:

    /* Remove this service */
    if (r < 0)
        service_free(s);

    avahi_string_list_free(txt);

    return r;
}