void avahi_init_proc_title(int argc, char **argv) {

#if !defined(HAVE_SETPROCTITLE) && defined(__linux__)

    unsigned i;
    char **new_environ, *endptr;

    /* This code is really really ugly. We make some memory layout
     * assumptions and reuse the environment array as memory to store
     * our process title in */

    for (i = 0; environ[i]; i++);

    endptr = i ? environ[i-1] + strlen(environ[i-1]) : argv[argc-1] + strlen(argv[argc-1]);

    argv_buffer = argv;
    argv_size = endptr - argv_buffer[0];

    /* Make a copy of environ */
    
    new_environ = avahi_malloc(sizeof(char*) * (i + 1));
    for (i = 0; environ[i]; i++)
        new_environ[i] = avahi_strdup(environ[i]);
    new_environ[i] = NULL;

    environ = new_environ;

#endif
}	
void NetworkServicesProviderAvahi::removeServiceInfo(ServiceInfo* i) 
{
    ASSERT(i);
    NetworkServicesProviderAvahi* p = i->provider;
    char* id;
    
    id = (char*) avahi_malloc(strlen(i->name) + strlen(i->type) + strlen(i->domain) + 4);
    sprintf(id, "%s.%s.%s.", i->name, i->type, i->domain);

    p->removeServiceDescription(id);

    AVAHI_LLIST_REMOVE(ServiceInfo, info, m_services, i);

    if (i->resolver)
        avahi_service_resolver_free(i->resolver);

    avahi_free(i->name);
    avahi_free(i->type);
    avahi_free(i->domain);
    avahi_free(i);
}
Exemple #3
0
static void inotify_callback(AvahiWatch *watch, int fd, AVAHI_GCC_UNUSED AvahiWatchEvent event, AVAHI_GCC_UNUSED void *userdata) {
    char* buffer;
    int n = 0;

    assert(fd == inotify_fd);
    assert(watch);

    ioctl(inotify_fd, FIONREAD, &n);
    if (n <= 0)
        n = 128;

    buffer = avahi_malloc(n);
    if (read(inotify_fd, buffer, n) < 0 ) {
        avahi_free(buffer);
        avahi_log_error("Failed to read inotify event: %s", avahi_strerror(errno));
        return;
    }
    avahi_free(buffer);

    avahi_log_info("Files changed, reloading.");
    reload_config();
}
void NetworkServicesProviderAvahi::serviceBrowserCallback(
    AVAHI_GCC_UNUSED AvahiServiceBrowser* b,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiBrowserEvent event,
    const char* name,
    const char* type,
    const char* domain,
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
    void* userdata) 
{
    NetworkServicesProviderAvahi* p = static_cast<NetworkServicesProviderAvahi*>(userdata);

    ASSERT(b);
    ASSERT(p);

    switch (event) {
    case AVAHI_BROWSER_NEW: 
        {
            ServiceInfo* info;

            printServiceLine('+', interface, protocol, name, type, domain);

            if ((info = p->findService(interface, protocol, name, type, domain))) {
                char* id;
                NetworkServiceDescription* desc;
                
                if (!(info->notify))
                    return;

                id = (char*) avahi_malloc(strlen(name) + strlen(type) + strlen(domain) + 4);
                sprintf(id, "%s.%s.%s.", name, type, domain);
                desc = p->getServiceDescriptionById(String::fromUTF8(id));
                if (desc) {
                    desc->setOnline(true);
                    p->notifyNetworkServiceChanged(desc);
                }
                avahi_free(id);
                info->notify = false;

                return;
            }

            p->addServiceInfo(interface, protocol, name, type, domain);

            break;

        }

    case AVAHI_BROWSER_REMOVE: 
        {
            ServiceInfo* info;

            if (!(info = p->findService(interface, protocol, name, type, domain)))
                return;

            if (info->notify) {
                p->removeServiceInfo(info);
                info->notify = false;
            }

            printServiceLine('-', interface, protocol, name, type, domain);
            break;
        }

    case AVAHI_BROWSER_FAILURE:
        LOG_ERROR("service_browser failed: %s\n", avahi_strerror(avahi_client_errno(p->m_avahiClient)));
        break;

    case AVAHI_BROWSER_CACHE_EXHAUSTED:
        break;

    case AVAHI_BROWSER_ALL_FOR_NOW:
        p->m_allForNow--;
        p->checkTerminate();
        break;
    }
}
void NetworkServicesProviderAvahi::serviceResolverCallback(
    AVAHI_GCC_UNUSED AvahiServiceResolver* r,
    AVAHI_GCC_UNUSED AvahiIfIndex interface,
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
    AvahiResolverEvent event,
    const char* name,
    const char* type,
    const char* domain,
    const char* hostName,
    const AvahiAddress* a,
    AVAHI_GCC_UNUSED uint16_t port,
    AvahiStringList* txt,
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
    void* userdata) 
{
    ServiceInfo* i = static_cast<ServiceInfo*>(userdata);
    NetworkServicesProviderAvahi* p = i->provider;

    ASSERT(r);
    ASSERT(i);

    switch (event) {
    case AVAHI_RESOLVER_FOUND: 
        {
            NetworkServiceDescription* desc;
            char address[AVAHI_ADDRESS_STR_MAX];
            char* id;
            char* ztype;
            char* url;
            char* config;

            avahi_address_snprint(address, sizeof(address), a);

            config = avahi_string_list_to_string(txt);

            printServiceLine('=', interface, protocol, name, type, domain);

            LOG(Network,
                "   hostname = [%s]\n"
                "   address = [%s]\n"
                "   port = [%u]\n"
                "   txt = [%s]\n",
                hostName,
                address,
                port,
                config);
    
            id = (char*) avahi_malloc(strlen(name) + strlen(type) + strlen(domain) + 4);
            sprintf(id, "%s.%s.%s.", name, type, domain);

            ztype = (char*) avahi_malloc(strlen(type) + strlen("zeroconf:") + 1);
            sprintf(ztype, "zeroconf:%s", type);

            url = (char*) avahi_malloc(strlen("http://") + strlen(hostName) + 1);
            sprintf(url, "http://%s", hostName);

            if (!(desc = p->getServiceDescriptionById(String::fromUTF8(id))))
                p->addServiceDescription(id, name, ztype, url, config);
            else {
                desc->setOnline(true);
                p->notifyNetworkServiceChanged(desc);
            }

            avahi_free(id);
            avahi_free(ztype);
            avahi_free(url);
            avahi_free(config);

            break;
        }

    case AVAHI_RESOLVER_FAILURE:

        LOG_ERROR("Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_client_errno(p->m_avahiClient)));
        break;
    }

    avahi_service_resolver_free(i->resolver);
    i->resolver = 0;

    p->m_resolving--;
    p->checkTerminate();
}
/* Register a distcc service in DNS-SD/mDNS.  If advertise_capabilities is
 * true, the registration will contain information about the distcc server's
 * capabilities.  If service_type is NULL, the default service type will be
 * used.  advertise_capabilities should be true when using the default
 * service type. */
void* dcc_zeroconf_register_extended(int advertise_capabilities,
                                     const char *service_type,
                                     uint16_t port,
                                     int n_cpus) {
    struct context *ctx = NULL;
    char hostname[_POSIX_HOST_NAME_MAX + 1];
    const AvahiPoll *threaded_poll;
    int len, error;

    ctx = calloc(1, sizeof(struct context));
    if (!ctx) {
        rs_log_crit("calloc() failed for ctx: %s", strerror(errno));
        goto fail;
    }

    ctx->advertise_capabilities = advertise_capabilities;
    ctx->port = port;
    ctx->n_cpus = n_cpus;

    /* Prepare service type.  Use the supplied value, or the default if
     * NULL was supplied. */
    if (service_type)
        ctx->service_type = strdup(service_type);
    else
        ctx->service_type = strdup(DCC_DNS_SERVICE_TYPE);
    if (!ctx->service_type) {
        rs_log_crit("strdup() failed for ctx->service_type: %s",
                    strerror(errno));
        goto fail;
    }

    /* Prepare service name.  This is just the chosen service type with
     * '@' and the hostname appended.  If this collides with anything else,
     * avahi_alternative_service_name will choose a replacement name. */
    if (gethostname(hostname, sizeof(hostname))) {
        rs_log_crit("gethostname() failed: %s", strerror(errno));
        goto fail;
    }

    /* Leave room for the '@' and trailing NUL. */
    len = strlen(ctx->service_type) + strlen(hostname) + 2;
    if (!(ctx->name = avahi_malloc(len))) {
        rs_log_crit("avahi_malloc() failed for ctx->name");
        goto fail;
    }

    snprintf(ctx->name, len, "%s@%s", ctx->service_type, hostname);

    /* Create the Avahi client. */
    if (!(ctx->threaded_poll = avahi_threaded_poll_new())) {
        rs_log_crit("Failed to create event loop object.");
        goto fail;
    }

    threaded_poll = avahi_threaded_poll_get(ctx->threaded_poll);

    if (!(ctx->client = avahi_client_new(threaded_poll, AVAHI_CLIENT_NO_FAIL,
                                         client_callback, ctx, &error))) {
        rs_log_crit("Failed to create client object: %s",
                    avahi_strerror(error));
        goto fail;
    }

    /* Create the mDNS event handler */
    if (avahi_threaded_poll_start(ctx->threaded_poll) < 0) {
        rs_log_crit("Failed to create thread.");
        goto fail;
    }

    return ctx;

fail:

    if (ctx)
        dcc_zeroconf_unregister(ctx);

    return NULL;
}