Example #1
0
void CZeroconfAvahi::addService(tServiceMap::mapped_type fp_service_info, AvahiClient* fp_client)
{
  assert(fp_client);
  CLog::Log(LOGDEBUG, "CZeroconfAvahi::addService() named: %s type: %s port:%i", fp_service_info->m_name.c_str(), fp_service_info->m_type.c_str(), fp_service_info->m_port);
  //create the group if it doesn't exist
  if (!fp_service_info->mp_group)
  {
    if (!(fp_service_info->mp_group = avahi_entry_group_new(fp_client, &CZeroconfAvahi::groupCallback, this)))
    {
      CLog::Log(LOGDEBUG, "CZeroconfAvahi::addService() avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(fp_client)));
      fp_service_info->mp_group = 0;
      return;
    }
  }


  // add entries to the group if it's empty
  int ret;
  if (avahi_entry_group_is_empty(fp_service_info->mp_group))
  {
    if ((ret = avahi_entry_group_add_service_strlst(fp_service_info->mp_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0),
                                             fp_service_info->m_name.c_str(),
                                             fp_service_info->m_type.c_str(), NULL, NULL, fp_service_info->m_port, fp_service_info->mp_txt) < 0))
    {
      if (ret == AVAHI_ERR_COLLISION)
      {
        char* alt_name = avahi_alternative_service_name(fp_service_info->m_name.c_str());
        fp_service_info->m_name = alt_name;
        avahi_free(alt_name);
        CLog::Log(LOGNOTICE, "CZeroconfAvahi::addService: Service name collision. Renamed to: %s", fp_service_info->m_name.c_str());
        addService(fp_service_info, fp_client);
        return;
      }
      CLog::Log(LOGERROR, "CZeroconfAvahi::addService(): failed to add service named:%s@$(HOSTNAME) type:%s port:%i. Error:%s :/ FIXME!",
                fp_service_info->m_name.c_str(), fp_service_info->m_type.c_str(), fp_service_info->m_port,  avahi_strerror(ret));
      return;
    }
  }

  // Tell the server to register the service
  if ((ret = avahi_entry_group_commit(fp_service_info->mp_group)) < 0)
  {
    CLog::Log(LOGERROR, "CZeroconfAvahi::addService(): Failed to commit entry group! Error:%s",  avahi_strerror(ret));
    // TODO what now? reset the group? free it?
  }
}
void ControllerDiscoveryMDNS::create_service( AvahiServer * server )
{
    if ( !group )
    {
        group = avahi_s_entry_group_new( server, avahi_entry_group_callback, this );

        if ( !group )
        {
            g_warning( "FAILED TO CREATE AVAHI ENTRY GROUP : %s", avahi_strerror( avahi_server_errno( server ) ) );
        }
    }

    if ( group )
    {
        if ( avahi_s_entry_group_is_empty( group ) )
        {
            int ret = AVAHI_OK;

            while ( true )
            {
                // TODO: this could loop forever...maybe we should bail at some stage

                ret = avahi_server_add_service( server, group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                                                AvahiPublishFlags( 0 ), name.c_str(), TP_REMOTE_MDNS_SERVICE, NULL, NULL, port, NULL );

                if ( ret == AVAHI_ERR_COLLISION )
                {
                    rename();
                }
                else
                {
                    break;
                }
            }

            if ( ret != AVAHI_OK )
            {
                g_warning( "FAILED TO ADD AVAHI SERVICE : %s", avahi_strerror( ret ) );
            }
            else
            {
                while ( true )
                {
                    // TODO: this could loop forever...maybe we should bail at some stage

                    ret = avahi_server_add_service( server, group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                                                    AvahiPublishFlags( 0 ), name.c_str(), TP_HTTP_MDNS_SERVICE, NULL, NULL, http_port, NULL );

                    if ( ret == AVAHI_ERR_COLLISION )
                    {
                        rename();
                    }
                    else
                    {
                        break;
                    }
                }


                if ( ret != AVAHI_OK )
                {
                    g_warning( "FAILED TO ADD AVAHI SERVICE : %s", avahi_strerror( ret ) );
                }
                else
                {
					ret = avahi_s_entry_group_commit( group );

					if ( ret != AVAHI_OK )
					{
						g_warning( "FAILED TO COMMIT AVAHI SERVICE : %s", avahi_strerror( ret ) );
					}
                }
            }
        }
    }
}
Example #3
0
void PublishAvahi::create_services(AvahiClient *c)
{
	assert(c);
	char *n;
	
	/// If this is the first time we're called, let's create a new entry group if necessary
	if (!group)
	{
		if (!(group = avahi_entry_group_new(c, entry_group_callback, this)))
		{
			logE << "avahi_entry_group_new() failed: " << avahi_strerror(avahi_client_errno(c)) << "\n";
			goto fail;
		}
	}

	/// If the group is empty (either because it was just created, or because it was reset previously, add our entries. 
	int ret;
	if (avahi_entry_group_is_empty(group))
	{
		logO << "Adding service '" << name << "'\n";

		/// We will now add two services and one subtype to the entry group
		for (const auto& service: services_)
		{
			if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0), name, service.name_.c_str(), NULL, NULL, service.port_, NULL)) < 0)
			{
				if (ret == AVAHI_ERR_COLLISION)
					goto collision;

				logE << "Failed to add " << service.name_ << " service: " << avahi_strerror(ret) << "\n";
				goto fail;
			}
		}

		/// Add an additional (hypothetic) subtype
/*		if ((ret = avahi_entry_group_add_service_subtype(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0), name, "_printer._tcp", NULL, "_magic._sub._printer._tcp") < 0))
		{
			fprintf(stderr, "Failed to add subtype _magic._sub._printer._tcp: %s\n", avahi_strerror(ret));
			goto fail;
		}
*/
		/// Tell the server to register the service
		if ((ret = avahi_entry_group_commit(group)) < 0)
		{
			logE << "Failed to commit entry group: " << avahi_strerror(ret) << "\n";
			goto fail;
		}
	}

	return;

collision:

	/// A service name collision with a local service happened. Let's pick a new name
	n = avahi_alternative_service_name(name);
	avahi_free(name);
	name = n;

	logO << "Service name collision, renaming service to '" << name << "'\n";

	avahi_entry_group_reset(group);

	create_services(c);
	return;

fail:
	avahi_simple_poll_quit(simple_poll);
}
Example #4
0
bool CZeroconfAvahi::doForceReAnnounceService(const std::string& fcr_identifier)
{
  bool ret = false;
  ScopedEventLoopBlock l_block(mp_poll);
  tServiceMap::iterator it = m_services.find(fcr_identifier);
  if (it != m_services.end() && it->second->mp_group)
  {
    // to force a reannounce on avahi its enough to reverse the txtrecord list
    it->second->mp_txt = avahi_string_list_reverse(it->second->mp_txt);

    // this will trigger the reannouncement
    if ((avahi_entry_group_update_service_txt_strlst(it->second->mp_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0),
                                              it->second->m_name.c_str(),
                                              it->second->m_type.c_str(), NULL, it->second->mp_txt)) >= 0)
      ret = true;
  }

  return ret;
}
Example #5
0
void PublishAvahi::create_services(AvahiClient *c)
{
	char *n, r[128];
	int ret;
	assert(c);

	/* If this is the first time we're called, let's create a new
		* entry group if necessary */

	if (!group)
	{
		if (!(group = avahi_entry_group_new(c, entry_group_callback, this)))
		{
			logE << "avahi_entry_group_new() failed: " << avahi_strerror(avahi_client_errno(c)) << "\n";
			goto fail;
		}
	}
	/* If the group is empty (either because it was just created, or
		* because it was reset previously, add our entries.  */

	if (avahi_entry_group_is_empty(group))
	{
		logO << "Adding service '" << name << "'\n";

		/* Create some random TXT data */
		snprintf(r, sizeof(r), "random=%i", rand());

		/* We will now add two services and one subtype to the entry
			* group. The two services have the same name, but differ in
			* the service type (IPP vs. BSD LPR). Only services with the
			* same name should be put in the same entry group. */

		/* Add the service for IPP */
/*        if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_PUBLISH_UNIQUE, name, "_ipp._tcp", NULL, NULL, 651, "test=blah", r, NULL)) < 0)
		{

			if (ret == AVAHI_ERR_COLLISION)
				goto collision;

			fprintf(stderr, "Failed to add _ipp._tcp service: %s\n", avahi_strerror(ret));
			goto fail;
		}
*/
		/* Add the same service for BSD LPR */
		for (size_t n=0; n<services.size(); ++n)
		{
			if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, services[n].proto_, AvahiPublishFlags(0), name, services[n].name_.c_str(), NULL, NULL, services[n].port_, NULL)) < 0)
			{

				if (ret == AVAHI_ERR_COLLISION)
					goto collision;

				logE << "Failed to add " << services[n].name_ << " service: " << avahi_strerror(ret) << "\n";
				goto fail;
			}
		}

		/* Add an additional (hypothetic) subtype */
/*        if ((ret = avahi_entry_group_add_service_subtype(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0), name, "_printer._tcp", NULL, "_magic._sub._printer._tcp") < 0))
		{
			fprintf(stderr, "Failed to add subtype _magic._sub._printer._tcp: %s\n", avahi_strerror(ret));
			goto fail;
		}
*/
		/* Tell the server to register the service */
		if ((ret = avahi_entry_group_commit(group)) < 0)
		{
			logE << "Failed to commit entry group: " << avahi_strerror(ret) << "\n";
			goto fail;
		}
	}

	return;

collision:

	/* A service name collision with a local service happened. Let's
		* pick a new name */
	n = avahi_alternative_service_name(name);
	avahi_free(name);
	name = n;

	logO << "Service name collision, renaming service to '" << name << "'\n";

	avahi_entry_group_reset(group);

	create_services(c);
	return;

fail:
	avahi_simple_poll_quit(simple_poll);
}
Example #6
0
void announcer::async_announce(const aware::contact& contact,
                               async_announce_handler h)
{
    assert(ptr != 0);

    handler = h;

    const AvahiPublishFlags flags = AvahiPublishFlags(0);
    const aware::contact::endpoint_type endpoint = contact.get_endpoint();
    // Use all network interfaces
    const AvahiIfIndex interface_index = AVAHI_IF_UNSPEC;
    // Use only a specific protocol
    const AvahiProtocol protocol =
        contact.get_endpoint().protocol() == boost::asio::ip::tcp::v6()
        ? AVAHI_PROTO_INET6
        : AVAHI_PROTO_INET;
    std::string name = contact.get_name();
    // FIXME: from contact (endpoint.protocol())
    std::string type = "_" + contact.get_type() + "._tcp";
    // Use .local
    const char *domain = 0;
    // Host name
    boost::asio::ip::address address = endpoint.address();
    std::string host = address.is_unspecified()
        ? "" // Use default host name
        : address.to_string();

    property_list properties;
    if (!contact.get_properties().empty())
    {
        properties = contact.get_properties();
        if (properties == 0)
        {
            boost::system::error_code error(boost::system::errc::not_enough_memory,
                                            boost::system::system_category());
            handler(error);
            return;
        }
    }

    while (true)
    {
        int rc = avahi_entry_group_add_service_strlst(ptr,
                                                      interface_index,
                                                      protocol,
                                                      flags,
                                                      name.c_str(),
                                                      type.c_str(),
                                                      domain,
                                                      host.empty() ? 0 : host.c_str(),
                                                      endpoint.port(),
                                                      properties);
        if (rc == AVAHI_ERR_COLLISION)
        {
            char *alternative = avahi_alternative_service_name(name.c_str());
            name = alternative;
            avahi_free(alternative);
        }
        else if (rc != AVAHI_OK)
        {
            handler(convert_error(rc));
            return;
        }
        else
        {
            break;
        }
    }
    commit(ptr);
}