Пример #1
0
static void go_to_initial_state(AvahiAnnouncer *a) {
    AvahiEntry *e;
    struct timeval tv;

    assert(a);
    e = a->entry;

    if ((e->flags & AVAHI_PUBLISH_UNIQUE) && !(e->flags & AVAHI_PUBLISH_NO_PROBE))
        a->state = AVAHI_PROBING;
    else if (!(e->flags & AVAHI_PUBLISH_NO_ANNOUNCE)) {

        if (!e->group || e->group->state == AVAHI_ENTRY_GROUP_ESTABLISHED)
            a->state = AVAHI_ANNOUNCING;
        else
            a->state = AVAHI_WAITING;

    } else
        a->state = AVAHI_ESTABLISHED;

    a->n_iteration = 1;
    a->sec_delay = 1;

    if (a->state == AVAHI_PROBING && e->group)
        e->group->n_probing++;

    if (a->state == AVAHI_PROBING)
        set_timeout(a, avahi_elapse_time(&tv, 0, AVAHI_PROBE_JITTER_MSEC));
    else if (a->state == AVAHI_ANNOUNCING)
        set_timeout(a, avahi_elapse_time(&tv, 0, AVAHI_ANNOUNCEMENT_JITTER_MSEC));
    else
        set_timeout(a, NULL);
}
Пример #2
0
static void reannounce(AvahiAnnouncer *a) {
    AvahiEntry *e;
    struct timeval tv;
        
    assert(a);
    e = a->entry;
	assert(e->type == AVAHI_ENTRY_MDNS);

    /* If the group this entry belongs to is not even commited, there's nothing to reannounce */
    if (e->group) {
		assert(e->group->type == AVAHI_GROUP_MDNS);
		if (e->group->state == AVAHI_ENTRY_GROUP_UNCOMMITED || e->group->state == AVAHI_ENTRY_GROUP_COLLISION) 
 	      return;
	}

    /* Because we might change state we decrease the probing counter first */
    if (a->state == AVAHI_PROBING && a->entry->group)
        a->entry->group->proto.mdns.n_probing--;
    
    if (a->state == AVAHI_PROBING ||
        (a->state == AVAHI_WAITING && (e->flags & AVAHI_PUBLISH_UNIQUE) && !(e->flags & AVAHI_PUBLISH_NO_PROBE)))

        /* We were probing or waiting after probe, so we restart probing from the beginning here */
        
        a->state = AVAHI_PROBING;
    else if (a->state == AVAHI_WAITING)

        /* We were waiting, but were not probing before, so we continue waiting  */
        a->state = AVAHI_WAITING;

    else if (e->flags & AVAHI_PUBLISH_NO_ANNOUNCE)
        
        /* No announcer needed */
        a->state = AVAHI_ESTABLISHED;

    else {
        
        /* Ok, let's restart announcing */
        a->state = AVAHI_ANNOUNCING;
    } 
        
    /* Now let's increase the probing counter again */
    if (a->state == AVAHI_PROBING && e->group)
        e->group->proto.mdns.n_probing++;
    
    a->n_iteration = 1;
    a->sec_delay = 1;

    if (a->state == AVAHI_PROBING)
        set_timeout(a, avahi_elapse_time(&tv, 0, AVAHI_PROBE_JITTER_MSEC));
    else if (a->state == AVAHI_ANNOUNCING) 
        set_timeout(a, avahi_elapse_time(&tv, 0, AVAHI_ANNOUNCEMENT_JITTER_MSEC));
    else
        set_timeout(a, NULL);
}
Пример #3
0
static dbus_bool_t add_timeout(DBusTimeout *dbus_timeout, void *userdata) {
    TimeoutData *timeout;
    ConnectionData *d = userdata;
    struct timeval tv;
    dbus_bool_t b;

    assert(dbus_timeout);
    assert(d);

    if (!(timeout = avahi_new(TimeoutData, 1)))
        return FALSE;

    timeout->dbus_timeout = dbus_timeout;
    timeout->poll_api = d->poll_api;
    timeout->ref = 1;

    if ((b = dbus_timeout_get_enabled(dbus_timeout)))
        avahi_elapse_time(&tv, dbus_timeout_get_interval(dbus_timeout), 0);

    if (!(timeout->avahi_timeout = d->poll_api->timeout_new(
              d->poll_api,
              b ? &tv : NULL,
              timeout_callback,
              timeout))) {
        avahi_free(timeout);
        return FALSE;
    }

    dbus_timeout_set_data(dbus_timeout, timeout, (DBusFreeFunction) timeout_data_unref);
    return TRUE;
}
Пример #4
0
static void sender_timeout_callback(AvahiTimeEvent *e, void *userdata) {
    AvahiWideAreaLookup *l = userdata;
    struct timeval tv;

    assert(l);

    /* Try another DNS server after three retries */
    if (l->n_send >= 3 && avahi_address_cmp(&l->engine->dns_servers[l->engine->current_dns_server], &l->dns_server_used) == 0) {
        next_dns_server(l->engine);

        if (avahi_address_cmp(&l->engine->dns_servers[l->engine->current_dns_server], &l->dns_server_used) == 0)
            /* There is no other DNS server, fail */
            l->n_send = 1000;
    }
    
    if (l->n_send >= 6) {
        avahi_log_warn(__FILE__": Query timed out.");
        avahi_server_set_errno(l->engine->server, AVAHI_ERR_TIMEOUT);
        l->callback(l->engine, AVAHI_BROWSER_FAILURE, AVAHI_LOOKUP_RESULT_WIDE_AREA, NULL, l->userdata);
        lookup_stop(l);
        return;
    }

    assert(l->packet);
    send_to_dns_server(l, l->packet);
    l->n_send++;

    avahi_time_event_update(e, avahi_elapse_time(&tv, 1000, 0));
}
Пример #5
0
static void start_timeout(AvahiSAddressResolver *r) {
    struct timeval tv;
    assert(r);

    if (r->time_event)
        return;

    avahi_elapse_time(&tv, TIMEOUT_MSEC, 0);
    r->time_event = avahi_time_event_new(r->server->time_event_queue, &tv, time_event_callback, r);
}
Пример #6
0
static int register_once() {
    AvahiClient *client = NULL;
    int error;
    int ret = 1;
    struct timeval tv;

    group = NULL;
    simple_poll = NULL;
    name = NULL;

    /* Allocate main loop object */
    if (!(simple_poll = avahi_simple_poll_new())) {
        fprintf(stderr, "Failed to create simple poll object.\n");
        goto fail;
    }

    name = avahi_strdup("MegaPrinter");

    /* Allocate a new client */
    client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error);

    /* Check wether creating the client object succeeded */
    if (!client) {
        fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
        goto fail;
    }

    /* After 10s quit. */
    avahi_simple_poll_get(simple_poll)->timeout_new(
        avahi_simple_poll_get(simple_poll),
        avahi_elapse_time(&tv, 300*10, 0),
        quit_callback,
        client);

    /* Run the main loop */
    avahi_simple_poll_loop(simple_poll);

    ret = 0;

fail:

    /* Cleanup things */

    if (client)
        avahi_client_free(client);

    if (simple_poll)
        avahi_simple_poll_free(simple_poll);

    avahi_free(name);

    return ret;
}
Пример #7
0
static void update_timeout(TimeoutData *timeout) {
    assert(timeout);
    assert(timeout->ref >= 1);

    if (dbus_timeout_get_enabled(timeout->dbus_timeout)) {
        struct timeval tv;
        avahi_elapse_time(&tv, dbus_timeout_get_interval(timeout->dbus_timeout), 0);
        timeout->poll_api->timeout_update(timeout->
                                      avahi_timeout, &tv);
    } else
        timeout->poll_api->timeout_update(timeout->avahi_timeout, NULL);

}
Пример #8
0
static void job_set_elapse_time(AvahiProbeScheduler *s, AvahiProbeJob *pj, unsigned msec, unsigned jitter) {
    struct timeval tv;

    assert(s);
    assert(pj);

    avahi_elapse_time(&tv, msec, jitter);

    if (pj->time_event)
        avahi_time_event_update(pj->time_event, &tv);
    else
        pj->time_event = avahi_time_event_new(s->time_event_queue, &tv, elapse_callback, pj);
}
Пример #9
0
static void job_set_elapse_time(AvahiQueryScheduler *s, AvahiQueryJob *qj, unsigned msec, unsigned jitter) {
    struct timeval tv;

    assert(s);
    assert(qj);

    avahi_elapse_time(&tv, msec, jitter);

    if (qj->time_event)
        avahi_time_event_update(qj->time_event, &tv);
    else
        qj->time_event = avahi_time_event_new(s->time_event_queue, &tv, elapse_callback, qj);
}
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
    AvahiClient *client = NULL;
    int error;
    int ret = 1;
    struct timeval tv;

    /* Allocate main loop object */
    if (!(simple_poll = avahi_simple_poll_new())) {
        fprintf(stderr, "Failed to create simple poll object.\n");
        goto fail;
    }

    name = avahi_strdup("MegaPrinter");

    /* Allocate a new client */
    client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error);

    /* Check wether creating the client object succeeded */
    if (!client) {
        fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
        goto fail;
    }

    /* After 10s do some weird modification to the service */
    avahi_simple_poll_get(simple_poll)->timeout_new(
        avahi_simple_poll_get(simple_poll),
        avahi_elapse_time(&tv, 1000*10, 0),
        modify_callback,
        client);

    /* Run the main loop */
    avahi_simple_poll_loop(simple_poll);

    ret = 0;

fail:

    /* Cleanup things */

    if (client)
        avahi_client_free(client);

    if (simple_poll)
        avahi_simple_poll_free(simple_poll);

    avahi_free(name);

    return ret;
}
Пример #11
0
int avahi_llmnr_query_scheduler_post(AvahiLLMNRQueryScheduler *s, AvahiLLMNRQuery *lq, int immediately) {
    AvahiLLMNRQueryJob *qj;
    struct timeval tv;

    assert(s);
    assert(lq);

    if (!(qj = job_new(s, lq)))
        return 0;

    qj->time_event = avahi_time_event_new(s->time_event_queue,
                                          avahi_elapse_time(&tv, 0, immediately ? 0 : AVAHI_LLMNR_JITTER),
                                          elapse_timeout_callback,
                                          qj);

    return 1;
}
Пример #12
0
void avahi_s_entry_group_check_probed(AvahiSEntryGroup *g, int immediately) {
    AvahiEntry *e;
    assert(g);
    assert(!g->dead && g->type == AVAHI_GROUP_MDNS);

    /* Check whether all group members have been probed */
    
    if (g->state != AVAHI_ENTRY_GROUP_REGISTERING || g->proto.mdns.n_probing > 0) 
        return;

    avahi_s_entry_group_change_state(g, AVAHI_ENTRY_GROUP_ESTABLISHED);

    if (g->dead)
        return;
    
    for (e = g->entries; e; e = e->by_group_next) {
		AvahiAnnouncer *a;
		assert(e->type == AVAHI_ENTRY_MDNS);
        
        for (a = e->proto.mdns.announcers; a; a = a->by_entry_next) {
            
            if (a->state != AVAHI_WAITING)
                continue;
            
            a->state = AVAHI_ANNOUNCING;

            if (immediately) {
                /* Shortcut */
                
                a->n_iteration = 1;
                next_state(a);
            } else {
                struct timeval tv;
                a->n_iteration = 0;
                avahi_elapse_time(&tv, 0, AVAHI_ANNOUNCEMENT_JITTER_MSEC);
                set_timeout(a, &tv);
            }
        }
    }
}
Пример #13
0
static void reschedule_llmnr_query_job(AvahiLLMNRQueryJob *qj) {
    struct timeval tv;

    assert(qj);
    assert(!avahi_record_list_is_empty(qj->lq->c_bit_clear));

    if(!(qj->prev_scheduled)) {

        qj->prev_scheduled = 1;
        avahi_elapse_time(&tv, AVAHI_LLMNR_INTERVAL + AVAHI_LLMNR_JITTER, 0);
        avahi_time_event_update(qj->time_event, &tv);

    } else {
        /* We have already waited but we still have not received any response/s
        with 'c' bit clear. */
        qj->lq->callback(qj->lq->interface->hardware->index, qj->lq->interface->protocol, NULL, qj->lq->userdata);
        /*avahi_time_event_free(qj->time_event);
        qj->time_event = NULL;*/
        avahi_llmnr_query_job_destroy(qj->scheduler, qj);
    }
    return;
}
Пример #14
0
int avahi_query_scheduler_post(AvahiQueryScheduler *s, AvahiKey *key, int immediately, unsigned *ret_id) {
    struct timeval tv;
    AvahiQueryJob *qj;

    assert(s);
    assert(key);

    if ((qj = find_history_job(s, key)))
        return 0;

    avahi_elapse_time(&tv, immediately ? 0 : AVAHI_QUERY_DEFER_MSEC, 0);

    if ((qj = find_scheduled_job(s, key))) {
        /* Duplicate questions suppression */

        if (avahi_timeval_compare(&tv, &qj->delivery) < 0) {
            /* If the new entry should be scheduled earlier,
             * update the old entry */
            qj->delivery = tv;
            avahi_time_event_update(qj->time_event, &qj->delivery);
        }

        qj->n_posted++;

    } else {

        if (!(qj = job_new(s, key, 0)))
            return 0; /* OOM */

        qj->delivery = tv;
        qj->time_event = avahi_time_event_new(s->time_event_queue, &qj->delivery, elapse_callback, qj);
    }

    if (ret_id)
        *ret_id = qj->id;

    return 1;
}
Пример #15
0
void AvahiSession::PublishPort(SCRendezvousProtocol proto, short port)
{
	if (!mClient) return;

	AvahiEntry* entry = new AvahiEntry;
	entry->mProto = proto;
	entry->mPort = port;
	entry->mRegistered = false;

	mMutex.lock();
	entry->mNext = mEntries;
	mEntries = entry;
	mMutex.unlock();

	avahi_threaded_poll_lock(mPoll);
	struct timeval tv;
	avahi_threaded_poll_get(mPoll)->timeout_new(
		avahi_threaded_poll_get(mPoll),
		avahi_elapse_time(&tv, 0, 0),
		modify_cb,
		this);
	avahi_threaded_poll_unlock(mPoll);
}
Пример #16
0
int avahi_probe_scheduler_post(AvahiProbeScheduler *s, AvahiRecord *record, int immediately) {
    AvahiProbeJob *pj;
    struct timeval tv;
    
    assert(s);
    assert(record);
    assert(!avahi_key_is_pattern(record->key));

    if ((pj = find_history_job(s, record)))
        return 0;

    avahi_elapse_time(&tv, immediately ? 0 : AVAHI_PROBE_DEFER_MSEC, 0);

    if ((pj = find_scheduled_job(s, record))) {

        if (avahi_timeval_compare(&tv, &pj->delivery) < 0) {
            /* If the new entry should be scheduled earlier, update the old entry */
            pj->delivery = tv;
            avahi_time_event_update(pj->time_event, &pj->delivery);
        }

        return 1;
    } else {
        /* Create a new job and schedule it */
        if (!(pj = job_new(s, record, 0)))
            return 0; /* OOM */
        
        pj->delivery = tv;
        pj->time_event = avahi_time_event_new(s->time_event_queue, &pj->delivery, elapse_callback, pj);

        
/*     avahi_log_debug("Accepted new probe job."); */

        return 1;
    }
}
Пример #17
0
static void start_server(AvahiTimeout *t, void *userdata) {
  int error;
  
  assert(t);
  
  if (stb) {
    DEBUG("Service type browser already exists");
    avahi_s_service_type_browser_free(stb);
    stb = NULL;
  }
  
  if (server) {
    DEBUG("Server already exists");
    avahi_server_free(server);
    server = NULL;
  }
  
  /* Allocate a new server */
  server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, server_callback, NULL, &error);
  
  /* Check whether creating the server object succeeded */
  if (!server) {
    ERROR("Failed to create server: %s", avahi_strerror(error));
    avahi_simple_poll_quit(simple_poll);
    return;
  }
  
  /* every UPDATE_INTERVAL seconds, shut down and re-create server. This
   * has the benefit of causing CSM to send queries to other nodes, prompting
   * them to re-multicast their services. This is done because mDNS seems to
   * be very unreliable on mesh, and often nodes don't get service announcements
   * or can't resolve them. */
  struct timeval tv = {0};
  avahi_elapse_time(&tv, 1000*UPDATE_INTERVAL, 0);
  avahi_simple_poll_get(simple_poll)->timeout_update(t, &tv);
}
Пример #18
0
static void resend_llmnr_query(AvahiLLMNRQueryJob *qj) {
    AvahiLLMNRQuery *lq = qj->lq;
    struct timeval tv;
    assert(qj);

    if(lq->type == AVAHI_LLMNR_SIMPLE_QUERY || lq->type == AVAHI_LLMNR_UNIQUENESS_VERIFICATION_QUERY) {
        /**Check whether we have already sent this query three times */
        if(qj->n_sent >= 3) {
            lq->callback(lq->interface->hardware->index, lq->interface->protocol, NULL, lq->userdata);
            avahi_llmnr_query_job_destroy(qj->scheduler, qj);
            /* Free Timeevent */
            /*			avahi_time_event_free(qj->time_event);
            			qj->time_event = NULL;*/

        } else {

            /* Send packet */
            avahi_interface_send_packet(lq->interface, qj->p, AVAHI_LLMNR);
            (qj->n_sent)++;
            /* Schedule further queries*/
            avahi_elapse_time(&tv, AVAHI_LLMNR_INTERVAL, 0);
            avahi_time_event_update(qj->time_event, &tv);
        }

    } else {

        assert(lq->type == AVAHI_LLMNR_CONFLICT_QUERY);
        assert(qj->n_sent == 1);

        /* Destroy this query */
        lq->callback(lq->interface->hardware->index, lq->interface->protocol, NULL, lq->userdata);
        avahi_llmnr_query_job_destroy(qj->scheduler, qj);
    }

    return;
}
Пример #19
0
AvahiWideAreaLookup *avahi_wide_area_lookup_new(
    AvahiWideAreaLookupEngine *e,
    AvahiKey *key,
    AvahiWideAreaLookupCallback callback,
    void *userdata) {
    
    struct timeval tv;
    AvahiWideAreaLookup *l, *t;
    uint8_t *p;

    assert(e);
    assert(key);
    assert(callback);
    assert(userdata);

    l = avahi_new(AvahiWideAreaLookup, 1);
    l->engine = e;
    l->dead = 0;
    l->key = avahi_key_ref(key);
    l->cname_key = avahi_key_new_cname(l->key);
    l->callback = callback;
    l->userdata = userdata;

    /* If more than 65K wide area quries are issued simultaneously,
     * this will break. This should be limited by some higher level */

    for (;; e->next_id++)
        if (!find_lookup(e, e->next_id))
            break; /* This ID is not yet used. */

    l->id = e->next_id++;
    
    /* We keep the packet around in case we need to repeat our query */
    l->packet = avahi_dns_packet_new(0);

    avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_ID, (uint16_t) l->id);
    avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(0, 0, 0, 0, 1, 0, 0, 0, 0, 0));

    p = avahi_dns_packet_append_key(l->packet, key, 0);
    assert(p);
    
    avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_QDCOUNT, 1);

    if (send_to_dns_server(l, l->packet) < 0) {
        avahi_log_error(__FILE__": Failed to send packet.");
        avahi_dns_packet_free(l->packet);
        avahi_key_unref(l->key);
        if (l->cname_key)
            avahi_key_unref(l->cname_key);
        avahi_free(l);
        return NULL;
    }

    l->n_send = 1;
    
    l->time_event = avahi_time_event_new(e->server->time_event_queue, avahi_elapse_time(&tv, 500, 0), sender_timeout_callback, l);

    avahi_hashmap_insert(e->lookups_by_id, &l->id, l);

    t = avahi_hashmap_lookup(e->lookups_by_key, l->key);
    AVAHI_LLIST_PREPEND(AvahiWideAreaLookup, by_key, t, l);
    avahi_hashmap_replace(e->lookups_by_key, avahi_key_ref(l->key), t);

    AVAHI_LLIST_PREPEND(AvahiWideAreaLookup, lookups, e->lookups, l);
    
    return l;
}
static void
init_local (void)
{
	int i;
	MateVFSResult res;
	
	if (!started_local) {
		AvahiSimplePoll *simple_poll;
		const AvahiPoll *poll;
		AvahiClient *client = NULL;
		AvahiServiceBrowser **sb;
		struct timeval tv;
		int error;
		
		started_local = TRUE;
		
		for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++) {
			MateVFSDNSSDBrowseHandle *handle;
			res = mate_vfs_dns_sd_browse (&handle,
						       "local",
						       dns_sd_types[i].type,
						       local_browse_callback,
						       NULL, NULL);
			if (res == MATE_VFS_OK) {
				dns_sd_types[i].handle = handle;
			}
		}

		simple_poll = avahi_simple_poll_new ();
		if (simple_poll == NULL) {
			g_warning ("Failed to create simple poll object");
			return;
		}

		poll = avahi_simple_poll_get (simple_poll);
		client = avahi_client_new (poll, 0, 
					   avahi_client_callback, simple_poll, &error);
		
		/* Check wether creating the client object succeeded */
		if (client == NULL) {
			g_warning ("Failed to create client: %s\n", avahi_strerror (error));
			avahi_simple_poll_free (simple_poll);
			return;
		}

		sb = g_new0 (AvahiServiceBrowser *, G_N_ELEMENTS (dns_sd_types));

		for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++) {
			sb[i] = avahi_service_browser_new (client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 
							   dns_sd_types[i].type, "local",
							   AVAHI_LOOKUP_USE_MULTICAST,
							   local_browse_callback_sync, simple_poll);
		}
		

		avahi_elapse_time (&tv, LOCAL_SYNC_BROWSE_DELAY_MSEC, 0);
		poll->timeout_new (poll, &tv, stop_poll_timeout,
				   (void *)simple_poll);

		/* Run the main loop util reply or timeout */
		for (;;)
			if (avahi_simple_poll_iterate (simple_poll, -1) != 0)
				break;

		for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++) {
			if (sb[i] != NULL) {
				avahi_service_browser_free (sb[i]);
			}
		}
		avahi_client_free (client);
		avahi_simple_poll_free (simple_poll);

					  
	}
Пример #21
0
int
main (AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[])
{
    GMainLoop *loop = NULL;
    const AvahiPoll *poll_api;
    AvahiGLibPoll *glib_poll;
    AvahiClient *client;
    struct timeval tv;
    const char *version;
    int error;

    /* Optional: Tell avahi to use g_malloc and g_free */
    avahi_set_allocator (avahi_glib_allocator ());

    /* Create the GLIB main loop */
    loop = g_main_loop_new (NULL, FALSE);

    /* Create the GLIB Adaptor */
    glib_poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);
    poll_api = avahi_glib_poll_get (glib_poll);

    /* Example, schedule a timeout event with the Avahi API */
    avahi_elapse_time (&tv,                         /* timeval structure */
            1000,                                   /* 1 second */
            0);                                     /* "jitter" - Random additional delay from 0 to this value */

    poll_api->timeout_new (poll_api,                /* The AvahiPoll object */
                      &tv,                          /* struct timeval indicating when to go activate */
                      avahi_timeout_event,          /* Pointer to function to call */
                      NULL);                        /* User data to pass to function */

    /* Schedule a timeout event with the glib api */
    g_timeout_add (5000,                            /* 5 seconds */
            avahi_timeout_event_glib,               /* Pointer to function callback */
            loop);                                  /* User data to pass to function */

    /* Create a new AvahiClient instance */
    client = avahi_client_new (poll_api,            /* AvahiPoll object from above */
                               0,
            avahi_client_callback,                  /* Callback function for Client state changes */
            loop,                                   /* User data */
            &error);                                /* Error return */

    /* Check the error return code */
    if (client == NULL)
    {
        /* Print out the error string */
        g_warning ("Error initializing Avahi: %s", avahi_strerror (error));

        goto fail;
    }

    /* Make a call to get the version string from the daemon */
    version = avahi_client_get_version_string (client);

    /* Check if the call suceeded */
    if (version == NULL)
    {
        g_warning ("Error getting version string: %s", avahi_strerror (avahi_client_errno (client)));

        goto fail;
    }

    g_message ("Avahi Server Version: %s", version);

    /* Start the GLIB Main Loop */
    g_main_loop_run (loop);

fail:
    /* Clean up */
    g_main_loop_unref (loop);
    avahi_client_free (client);
    avahi_glib_poll_free (glib_poll);

    return 0;
}
Пример #22
0
int main(int argc, char*argv[]) {
    int ret = 1;

    argp_program_version = "1.0";
    static char doc[] = "Commotion Service Manager";
    static struct argp_option options[] = {
      {"bind", 'b', "URI", 0, "commotiond management socket"},
      {"nodaemon", 'n', 0, 0, "Do not fork into the background" },
      {"out", 'o', "FILE", 0, "Output file to write services to when USR1 signal is received" },
      {"pid", 'p', "FILE", 0, "Specify PID file"},
#ifdef USE_UCI
      {"uci", 'u', 0, 0, "Store service cache in UCI" },
#endif
      { 0 }
    };
    
    /* Set defaults */
    arguments.co_sock = DEFAULT_CO_SOCK;
#ifdef USE_UCI
    arguments.uci = 0;
#endif
    arguments.nodaemon = 0;
    arguments.output_file = DEFAULT_FILENAME;
    arguments.pid_file = PIDFILE;
    
    static struct argp argp = { options, parse_opt, NULL, doc };
    
    argp_parse (&argp, argc, argv, 0, 0, &arguments);
    //fprintf(stdout,"uci: %d, out: %s\n",arguments.uci,arguments.output_file);
    
    if (!arguments.nodaemon)
      daemon_start(arguments.pid_file);
    
    CHECK(co_init(),"Failed to initialize Commotion client");
    
    struct sigaction sa = {0};
    sa.sa_handler = print_services;
    CHECK(sigaction(SIGUSR1,&sa,NULL) == 0, "Failed to set signal handler");
    sa.sa_handler = shutdown;
    CHECK(sigaction(SIGINT,&sa,NULL) == 0, "Failed to set signal handler");
    CHECK(sigaction(SIGTERM,&sa,NULL) == 0, "Failed to set signal handler");

    /* Initialize the psuedo-RNG */
    srand(time(NULL));

    /* Allocate main loop object */
    CHECK((simple_poll = avahi_simple_poll_new()),"Failed to create simple poll object.");

    /* Do not publish any local records */
    avahi_server_config_init(&config);
    config.publish_hinfo = 0;
    config.publish_addresses = 0;
    config.publish_workstation = 0;
    config.publish_domain = 0;

    /* Set a unicast DNS server for wide area DNS-SD */
    avahi_address_parse("192.168.50.1", AVAHI_PROTO_UNSPEC, &config.wide_area_servers[0]);
    config.n_wide_area_servers = 1;
    config.enable_wide_area = 1;

    // Start timer to create server
    struct timeval tv = {0};
    avahi_elapse_time(&tv, 0, 0);
    avahi_simple_poll_get(simple_poll)->timeout_new(avahi_simple_poll_get(simple_poll), &tv, start_server, NULL); // create expiration event for service
    
    /* Run the main loop */
    avahi_simple_poll_loop(simple_poll);
    
    ret = 0;

error:

    /* Free the configuration data */
    avahi_server_config_free(&config);

    co_shutdown();

    /* Cleanup things */
    if (stb)
        avahi_s_service_type_browser_free(stb);

    if (server)
        avahi_server_free(server);
    
    if (simple_poll)
        avahi_simple_poll_free(simple_poll);

    return ret;
}
int
csm_update_service(csm_service_list *services, csm_service *s, csm_ctx *ctx, int validate)
{
  if (validate)
    CHECK(csm_validate_fields(ctx, s), "Service doesn't validate");
//   assert(s->lifetime);
  long lifetime = s->lifetime;
  
  // check if service is attached to service_list
  CHECK(co_list_contains(services->services, (co_obj_t*)container_of(s, co_service_t, service)),
	"Cannot update service not in service list");
  
  // detach s->fields from s and attach to services->service_fields
  if (!co_list_contains(services->service_fields, s->fields)) {
    co_obj_t *fields = s->fields;
    hattach(fields, NULL);
    CHECK(co_list_append(services->service_fields, fields),
	  "Failed to add service fields to service list");
  }
  
  /* Create or verify signature */
  if (s->signature)
    CHECK(csm_verify_signature(s),"Invalid signature");
  else
    CHECK(csm_create_signature(s),"Failed to create signature");
  
  /* Set expiration timer on the service */
#ifdef USE_UCI
  long def_lifetime = default_lifetime();
  if (lifetime == 0 || (def_lifetime < lifetime && def_lifetime > 0))
    lifetime = def_lifetime;
#endif
  if (lifetime > 0) {
    struct timeval tv;
    avahi_elapse_time(&tv, 1000*lifetime, 0);
    time_t current_time = time(NULL);
    // create expiration event for service
    s->timeout = avahi_simple_poll_get(simple_poll)->timeout_new(avahi_simple_poll_get(simple_poll),
								       &tv,
								       _csm_expire_service,
								       s);
    /* Convert lifetime period into timestamp */
    if (current_time != ((time_t)-1)) {
      struct tm *timestr = localtime(&current_time);
      timestr->tm_sec += lifetime;
      current_time = mktime(timestr);
      char *c_time_string = ctime(&current_time);
      if (c_time_string) {
	c_time_string[strlen(c_time_string)-1] = '\0'; /* ctime adds \n to end of time string; remove it */
	s->expiration = h_strdup(c_time_string);
	CHECK_MEM(s->expiration);
	service_attach(s->expiration, s);
      }
    }
  }
  
  // finalize service by running update handlers
  csm_services_commit(services);
  
  return 1;
error:
  return 0;
}
Пример #24
0
int avahi_response_scheduler_post(AvahiResponseScheduler *s, AvahiRecord *record, int flush_cache, const AvahiAddress *querier, int immediately) {
    AvahiResponseJob *rj;
    struct timeval tv;
/*     char *t; */
    
    assert(s);
    assert(record);

    assert(!avahi_key_is_pattern(record->key));

/*     t = avahi_record_to_string(record); */
/*     avahi_log_debug("post %i %s", immediately, t); */
/*     avahi_free(t); */

    /* Check whether this response is suppressed */
    if (querier &&
        (rj = find_suppressed_job(s, record, querier)) &&
        avahi_record_is_goodbye(record) == avahi_record_is_goodbye(rj->record) &&
        rj->record->ttl >= record->ttl/2) {

/*         avahi_log_debug("Response suppressed by known answer suppression.");  */
        return 0;
    }

    /* Check if we already sent this response recently */
    if ((rj = find_history_job(s, record))) {

        if (avahi_record_is_goodbye(record) == avahi_record_is_goodbye(rj->record) &&
            rj->record->ttl >= record->ttl/2 &&
            (rj->flush_cache || !flush_cache)) {
/*             avahi_log_debug("Response suppressed by local duplicate suppression (history)");  */
            return 0;
        }

        /* Outdated ... */
        job_free(s, rj);
    }

    avahi_elapse_time(&tv, immediately ? 0 : AVAHI_RESPONSE_DEFER_MSEC, immediately ? 0 : AVAHI_RESPONSE_JITTER_MSEC);
         
    if ((rj = find_scheduled_job(s, record))) {
/*          avahi_log_debug("Response suppressed by local duplicate suppression (scheduled)"); */

        /* Update a little ... */

        /* Update the time if the new is prior to the old */
        if (avahi_timeval_compare(&tv, &rj->delivery) < 0) {
            rj->delivery = tv;
            avahi_time_event_update(rj->time_event, &rj->delivery);
        }

        /* Update the flush cache bit */
        if (flush_cache)
            rj->flush_cache = 1;

        /* Update the querier field */
        if (!querier || (rj->querier_valid && avahi_address_cmp(querier, &rj->querier) != 0))
            rj->querier_valid = 0;

        /* Update record data (just for the TTL) */
        avahi_record_unref(rj->record);
        rj->record = avahi_record_ref(record);

        return 1;
    } else {
/*         avahi_log_debug("Accepted new response job.");  */

        /* Create a new job and schedule it */
        if (!(rj = job_new(s, record, AVAHI_SCHEDULED)))
            return 0; /* OOM */
        
        rj->delivery = tv;
        rj->time_event = avahi_time_event_new(s->time_event_queue, &rj->delivery, elapse_callback, rj);
        rj->flush_cache = flush_cache;

        if ((rj->querier_valid = !!querier))
            rj->querier = *querier;

        return 1;
    }
}
Пример #25
0
static void next_state(AvahiAnnouncer *a) {
    assert(a);

    if (a->state == AVAHI_WAITING) {

        assert(a->entry->group);

        avahi_s_entry_group_check_probed(a->entry->group, 1);

    } else if (a->state == AVAHI_PROBING) {

        if (a->n_iteration >= 4) {
            /* Probing done */

            if (a->entry->group) {
                assert(a->entry->group->n_probing);
                a->entry->group->n_probing--;
            }

            if (a->entry->group && a->entry->group->state == AVAHI_ENTRY_GROUP_REGISTERING)
                a->state = AVAHI_WAITING;
            else {
                a->state = AVAHI_ANNOUNCING;
                a->n_iteration = 1;
            }

            set_timeout(a, NULL);
            next_state(a);
        } else {
            struct timeval tv;

            avahi_interface_post_probe(a->interface, a->entry->record, 0);

            avahi_elapse_time(&tv, AVAHI_PROBE_INTERVAL_MSEC, 0);
            set_timeout(a, &tv);

            a->n_iteration++;
        }

    } else if (a->state == AVAHI_ANNOUNCING) {

        if (a->entry->flags & AVAHI_PUBLISH_UNIQUE)
            /* Send the whole rrset at once */
            avahi_server_prepare_matching_responses(a->server, a->interface, a->entry->record->key, 0);
        else
            avahi_server_prepare_response(a->server, a->interface, a->entry, 0, 0);

        avahi_server_generate_response(a->server, a->interface, NULL, NULL, 0, 0, 0);

        if (++a->n_iteration >= 4) {
            /* Announcing done */

            a->state = AVAHI_ESTABLISHED;

            set_timeout(a, NULL);
        } else {
            struct timeval tv;
            avahi_elapse_time(&tv, a->sec_delay*1000, AVAHI_ANNOUNCEMENT_JITTER_MSEC);

            if (a->n_iteration < 10)
                a->sec_delay *= 2;

            set_timeout(a, &tv);
        }
    }
}
Пример #26
0
gboolean
daap_mdns_setup ()
{
	const AvahiPoll *av_poll;

	GMainLoop *ml = NULL;
	gint errval;
	struct timeval tv;
	browse_callback_userdata_t *browse_userdata;

	if (gl_poll) {
		goto fail;
	}

	browse_userdata = g_new0 (browse_callback_userdata_t, 1);

	avahi_set_allocator (avahi_glib_allocator ());

	ml = g_main_loop_new (NULL, FALSE);

	gl_poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);
	av_poll = avahi_glib_poll_get (gl_poll);

	avahi_elapse_time (&tv, 2000, 0);
	av_poll->timeout_new (av_poll, &tv, daap_mdns_timeout, NULL);

	client = avahi_client_new (av_poll, 0, daap_mdns_client_cb, ml, &errval);
	if (!client) {
		goto fail;
	}

	browse_userdata->client = client;
	browse_userdata->mainloop = ml;

	browser = avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
	                                     AVAHI_PROTO_UNSPEC, "_daap._tcp", NULL,
	                                     0, daap_mdns_browse_cb,
	                                     browse_userdata);
	if (!browser) {
		goto fail;
	}

	return TRUE;

fail:
	if (ml)
		g_main_loop_unref (ml);

	if (client)
		avahi_client_free (client);
	client = NULL;
	browser = NULL;

	g_free (browse_userdata);

	if (gl_poll)
		avahi_glib_poll_free (gl_poll);
	gl_poll = NULL;

	return FALSE;
}
Пример #27
0
static void browse_callback(
    AvahiServiceBrowser *b,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiBrowserEvent event,
    const char *name,
    const char *type,
    const char *domain,
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
    void* userdata) {
    
    AvahiClient *c = userdata;
    const AvahiPoll *api = avahi_simple_poll_get (simple_poll);
    struct timeval *tv;

    assert(b);

    /* Called whenever a new services becomes available on the LAN or is removed from the LAN */

    switch (event) {
        case AVAHI_BROWSER_FAILURE:
            
            fprintf(stderr, "(Browser) %s\n", 
					avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
            avahi_simple_poll_quit(simple_poll);
            return;

        case AVAHI_BROWSER_NEW:
            /* Count the pending resolvers so we know when we can quit. */
            n_pending_resolvers++;

            /* We ignore the returned resolver object. In the callback
               function we free it. If the server is terminated before
               the callback function is called the server will free
               the resolver for us. */

            if (!(avahi_service_resolver_new(c, interface, 
											 protocol, name, 
											 type, domain, 
											 AVAHI_PROTO_UNSPEC, 0, resolve_callback, c)))
                fprintf(stderr, "Failed to resolve service '%s': %s\n", 
						name, avahi_strerror(avahi_client_errno(c)));
            
            break;

        case AVAHI_BROWSER_REMOVE:
			break;
        case AVAHI_BROWSER_ALL_FOR_NOW:
            /* The all for now event is emitted when each published service was
               announced by the new event (handled above). But there still might
               be some pending resolvers, so we have to wait for the resolvers
               to be finished, before quitting the main loop. */

            tv = avahi_malloc0 (sizeof (struct timeval));
            avahi_elapse_time (tv, 200, 0);
            api->timeout_new (api, tv, timeout_callback, tv);
            break;
        case AVAHI_BROWSER_CACHE_EXHAUSTED:
            break;
    }
}