<commit_before>/*
 * Copyright (c) 2013-2014 Red Hat.
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

#include <assert.h>
#include <avahi-client/publish.h>
#include <avahi-client/lookup.h>
#include <avahi-common/alternative.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/thread-watch.h>
#include <avahi-common/timeval.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
#include <avahi-common/domain.h>

#include "pmapi.h"
#include "impl.h"
#include "internal.h"
#include "avahi.h"

/* Support for servers advertising their presence. */
static AvahiThreadedPoll	*threadedPoll;
static AvahiClient		*client;
static AvahiEntryGroup		*group;

static __pmServerPresence	**activeServices;
static int			nActiveServices;
static int			szActiveServices;

struct __pmServerAvahiPresence {
    char	*serviceName;
    char	*serviceTag;
    int		collisions;
};

static void entryGroupCallback(AvahiEntryGroup *, AvahiEntryGroupState, void *);

static int
renameService(__pmServerPresence *s)
{
    /*
     * Each service must have a unique name on the local network.
     * When there is a collision, we try to rename the service.
     * However, we need to limit the number of attempts, since the
     * service namespace could be maliciously flooded with service
     * names designed to maximize collisions.
     * Arbitrarily choose a limit of 65535, which is the number of
     * TCP ports.
     */
    ++s->avahi->collisions;
    if (s->avahi->collisions >= 65535) {
	__pmNotifyErr(LOG_ERR, "Too many service name collisions for Avahi service %s",
		      s->avahi->serviceTag);
	return -EBUSY;
    }

    /*
     * Use the avahi-supplied function to generate a new service name.
     */
    char *n = avahi_alternative_service_name(s->avahi->serviceName);

    if (pmDebug & DBG_TRACE_DISCOVERY)
	__pmNotifyErr(LOG_INFO, "Avahi service name collision, renaming service '%s' to '%s'",
		      s->avahi->serviceName, n);
    avahi_free(s->avahi->serviceName);
    s->avahi->serviceName = n;

    return 0;
}

static int
renameServices(void)
{
    int i;
    int rc = 0;
    __pmServerPresence *s;

    for (i = 0; i < szActiveServices; ++i) {
	s = activeServices[i];
	if (s == NULL)
	    continue; /* empty entry */
	if ((rc = renameService(s)) < 0)
	    break;
    }

    return rc;
}

static void
createServices(AvahiClient *c)
{
    __pmServerPresence *s;
    int ret;
    int i;

    assert (c);

     /*
      * Create a new entry group, if necessary, or reset the existing one.
      */
    if (group == NULL) {
	if ((group = avahi_entry_group_new(c, entryGroupCallback, NULL)) == NULL) {
 	    __pmNotifyErr(LOG_ERR, "avahi_entry_group_new () failed: %s",
 			  avahi_strerror (avahi_client_errno(c)));
	    return;
 	}
    }
    else
	avahi_entry_group_reset(group);

    /*
     * We will now add our services to the entry group.
     */
    for (i = 0; i < szActiveServices; ++i) {
	s = activeServices[i];
	if (s == NULL)
	    continue; /* empty table entry */

	if (pmDebug & DBG_TRACE_DISCOVERY)
	    __pmNotifyErr(LOG_INFO, "Adding %s Avahi service on port %d",
			  s->avahi->serviceName, s->port);

	/* Loop until no collisions */
	for (;;) {
	    ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC,
						AVAHI_PROTO_UNSPEC,
						(AvahiPublishFlags)0,
						s->avahi->serviceName,
						s->avahi->serviceTag,
						NULL, NULL, s->port, NULL);
	    if (ret == AVAHI_OK)
		break; /* success! */
	    if (ret == AVAHI_ERR_COLLISION) {
		/*<commit_msg>libpcp: make avahi_entry_group_new diagnostic debug-conditional<commit_after>/*
 * Copyright (c) 2013-2014 Red Hat.
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

#include <assert.h>
#include <avahi-client/publish.h>
#include <avahi-client/lookup.h>
#include <avahi-common/alternative.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/thread-watch.h>
#include <avahi-common/timeval.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
#include <avahi-common/domain.h>

#include "pmapi.h"
#include "impl.h"
#include "internal.h"
#include "avahi.h"

/* Support for servers advertising their presence. */
static AvahiThreadedPoll	*threadedPoll;
static AvahiClient		*client;
static AvahiEntryGroup		*group;

static __pmServerPresence	**activeServices;
static int			nActiveServices;
static int			szActiveServices;

struct __pmServerAvahiPresence {
    char	*serviceName;
    char	*serviceTag;
    int		collisions;
};

static void entryGroupCallback(AvahiEntryGroup *, AvahiEntryGroupState, void *);

static int
renameService(__pmServerPresence *s)
{
    /*
     * Each service must have a unique name on the local network.
     * When there is a collision, we try to rename the service.
     * However, we need to limit the number of attempts, since the
     * service namespace could be maliciously flooded with service
     * names designed to maximize collisions.
     * Arbitrarily choose a limit of 65535, which is the number of
     * TCP ports.
     */
    ++s->avahi->collisions;
    if (s->avahi->collisions >= 65535) {
	__pmNotifyErr(LOG_ERR, "Too many service name collisions for Avahi service %s",
		      s->avahi->serviceTag);
	return -EBUSY;
    }

    /*
     * Use the avahi-supplied function to generate a new service name.
     */
    char *n = avahi_alternative_service_name(s->avahi->serviceName);

    if (pmDebug & DBG_TRACE_DISCOVERY)
	__pmNotifyErr(LOG_INFO, "Avahi service name collision, renaming service '%s' to '%s'",
		      s->avahi->serviceName, n);
    avahi_free(s->avahi->serviceName);
    s->avahi->serviceName = n;

    return 0;
}

static int
renameServices(void)
{
    int i;
    int rc = 0;
    __pmServerPresence *s;

    for (i = 0; i < szActiveServices; ++i) {
	s = activeServices[i];
	if (s == NULL)
	    continue; /* empty entry */
	if ((rc = renameService(s)) < 0)
	    break;
    }

    return rc;
}

static void
createServices(AvahiClient *c)
{
    __pmServerPresence *s;
    int ret;
    int i;

    assert(c);

     /*
      * Create a new entry group, if necessary, or reset the existing one.
      */
    if (group == NULL) {
	if ((group = avahi_entry_group_new(c, entryGroupCallback, NULL)) == NULL) {
	    if (pmDebug & DBG_TRACE_DISCOVERY)
		__pmNotifyErr(LOG_ERR, "avahi_entry_group_new failed: %s",
			  avahi_strerror(avahi_client_errno(c)));
	    return;
	}
    }
    else
	avahi_entry_group_reset(group);

    /*
     * We will now add our services to the entry group.
     */
    for (i = 0; i < szActiveServices; ++i) {
	s = activeServices[i];
	if (s == NULL)
	    continue; /* empty table entry */

	if (pmDebug & DBG_TRACE_DISCOVERY)
	    __pmNotifyErr(LOG_INFO, "Adding %s Avahi service on port %d",
			  s->avahi->serviceName, s->port);

	/* Loop until no collisions */
	for (;;) {
	    ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC,
						AVAHI_PROTO_UNSPEC,
						(AvahiPublishFlags)0,
						s->avahi->serviceName,
						s->avahi->serviceTag,
						NULL, NULL, s->port, NULL);
	    if (ret == AVAHI_OK)
		break; /* success! */
	    if (ret == AVAHI_ERR_COLLISION) {
		/*
{'fraction_non_alphanumeric': 0.11136107986501688, 'fraction_numerical': 0.006249218847644044, 'mean_word_length': 3.3021505376344087, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5863969', 'n_tokens_mistral': 2892, 'n_tokens_neox': 2624, 'n_words': 801}