probe-sched.c revision 4ff0807c04fcc239de52a793bceb88e7f3408f3f
128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering/* $Id$ */
228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering/***
428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  This file is part of avahi.
528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  avahi is free software; you can redistribute it and/or modify it
728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  under the terms of the GNU Lesser General Public License as
828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  published by the Free Software Foundation; either version 2.1 of the
928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  License, or (at your option) any later version.
1028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
1128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  avahi is distributed in the hope that it will be useful, but WITHOUT
1228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
1428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  Public License for more details.
1528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
1628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  You should have received a copy of the GNU Lesser General Public
1728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  License along with avahi; if not, write to the Free Software
1828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  USA.
2028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering***/
2128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
2228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering#ifdef HAVE_CONFIG_H
2328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering#include <config.h>
2428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering#endif
2528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
2628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering#include "probe-sched.h"
2728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering#include "util.h"
2828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
294ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering#define AVAHI_PROBE_HISTORY_MSEC 150
304ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering#define AVAHI_PROBE_DEFER_MSEC 50
3128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringtypedef struct AvahiProbeJob AvahiProbeJob;
3328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringstruct AvahiProbeJob {
3528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeScheduler *scheduler;
3628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiTimeEvent *time_event;
3728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    gboolean chosen; /* Use for packet assembling */
394ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    gboolean done;
4028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    GTimeVal delivery;
4128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
4228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiRecord *record;
4328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
4428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AVAHI_LLIST_FIELDS(AvahiProbeJob, jobs);
4528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering};
4628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
4728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringstruct AvahiProbeScheduler {
4828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiInterface *interface;
4928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiTimeEventQueue *time_event_queue;
5028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
5128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AVAHI_LLIST_HEAD(AvahiProbeJob, jobs);
524ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AVAHI_LLIST_HEAD(AvahiProbeJob, history);
5328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering};
5428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
554ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poetteringstatic AvahiProbeJob* job_new(AvahiProbeScheduler *s, AvahiRecord *record, gboolean done) {
5628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeJob *pj;
5728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
5828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(s);
5928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(record);
6028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
6128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    pj = g_new(AvahiProbeJob, 1);
6228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    pj->scheduler = s;
6328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    pj->record = avahi_record_ref(record);
6428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    pj->time_event = NULL;
6528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    pj->chosen = FALSE;
664ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
674ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if ((pj->done = done))
684ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        AVAHI_LLIST_PREPEND(AvahiProbeJob, jobs, s->history, pj);
694ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    else
704ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        AVAHI_LLIST_PREPEND(AvahiProbeJob, jobs, s->jobs, pj);
7128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
7228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    return pj;
7328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
7428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
7528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringstatic void job_free(AvahiProbeScheduler *s, AvahiProbeJob *pj) {
7628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(pj);
7728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
7828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    if (pj->time_event)
7928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        avahi_time_event_queue_remove(s->time_event_queue, pj->time_event);
8028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
814ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if (pj->done)
824ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        AVAHI_LLIST_REMOVE(AvahiProbeJob, jobs, s->history, pj);
834ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    else
844ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        AVAHI_LLIST_REMOVE(AvahiProbeJob, jobs, s->jobs, pj);
8528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
8628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_record_unref(pj->record);
8728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_free(pj);
8828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
8928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
904ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poetteringstatic void elapse_callback(AvahiTimeEvent *e, gpointer data);
914ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
924ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poetteringstatic void job_set_elapse_time(AvahiProbeScheduler *s, AvahiProbeJob *pj, guint msec, guint jitter) {
934ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    GTimeVal tv;
944ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
954ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    g_assert(s);
964ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    g_assert(pj);
974ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
984ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    avahi_elapse_time(&tv, msec, jitter);
994ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1004ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if (pj->time_event)
1014ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        avahi_time_event_queue_update(s->time_event_queue, pj->time_event, &tv);
1024ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    else
1034ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        pj->time_event = avahi_time_event_queue_add(s->time_event_queue, &tv, elapse_callback, pj);
1044ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering}
1054ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1064ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poetteringstatic void job_mark_done(AvahiProbeScheduler *s, AvahiProbeJob *pj) {
1074ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    g_assert(s);
1084ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    g_assert(pj);
1094ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1104ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    g_assert(!pj->done);
1114ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1124ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AVAHI_LLIST_REMOVE(AvahiProbeJob, jobs, s->jobs, pj);
1134ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AVAHI_LLIST_PREPEND(AvahiProbeJob, jobs, s->history, pj);
1144ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1154ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    pj->done = TRUE;
1164ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1174ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    job_set_elapse_time(s, pj, AVAHI_PROBE_HISTORY_MSEC, 0);
1184ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    g_get_current_time(&pj->delivery);
1194ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering}
12028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
12128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart PoetteringAvahiProbeScheduler *avahi_probe_scheduler_new(AvahiInterface *i) {
12228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeScheduler *s;
12328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
12428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(i);
12528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
12628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    s = g_new(AvahiProbeScheduler, 1);
12728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    s->interface = i;
12828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    s->time_event_queue = i->monitor->server->time_event_queue;
12928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
13028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AVAHI_LLIST_HEAD_INIT(AvahiProbeJob, s->jobs);
1314ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AVAHI_LLIST_HEAD_INIT(AvahiProbeJob, s->history);
13228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
13328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    return s;
13428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
13528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
13628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringvoid avahi_probe_scheduler_free(AvahiProbeScheduler *s) {
13728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(s);
13828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
13928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_probe_scheduler_clear(s);
14028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_free(s);
14128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
14228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
14328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringvoid avahi_probe_scheduler_clear(AvahiProbeScheduler *s) {
14428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(s);
14528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
14628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    while (s->jobs)
14728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        job_free(s, s->jobs);
1484ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    while (s->history)
1494ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        job_free(s, s->history);
15028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
15128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
15228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringstatic gboolean packet_add_probe_query(AvahiProbeScheduler *s, AvahiDnsPacket *p, AvahiProbeJob *pj) {
15328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    guint size;
15428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiKey *k;
15528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    gboolean b;
15628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
15728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(s);
15828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(p);
15928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(pj);
16028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
16128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(!pj->chosen);
16228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
16328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Estimate the size for this record */
16428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    size =
16528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        avahi_key_get_estimate_size(pj->record->key) +
16628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        avahi_record_get_estimate_size(pj->record);
16728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
16828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Too large */
16928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    if (size > avahi_dns_packet_space(p))
17028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        return FALSE;
17128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
17228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Create the probe query */
17328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    k = avahi_key_new(pj->record->key->name, pj->record->key->class, AVAHI_DNS_TYPE_ANY);
17428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    b = !!avahi_dns_packet_append_key(p, k, FALSE);
17528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(b);
17628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
17728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Mark this job for addition to the packet */
17828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    pj->chosen = TRUE;
17928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
18028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Scan for more jobs whith matching key pattern */
18128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    for (pj = s->jobs; pj; pj = pj->jobs_next) {
18228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (pj->chosen)
18328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            continue;
18428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
18528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        /* Does the record match the probe? */
18628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (k->class != pj->record->key->class || !avahi_domain_equal(k->name, pj->record->key->name))
18728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            continue;
18828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
18928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        /* This job wouldn't fit in */
19028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (avahi_record_get_estimate_size(pj->record) > avahi_dns_packet_space(p))
19128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            break;
19228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
19328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        /* Mark this job for addition to the packet */
19428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        pj->chosen = TRUE;
19528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    }
19628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
19728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_key_unref(k);
19828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
19928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    return TRUE;
20028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
20128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
20228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringstatic void elapse_callback(AvahiTimeEvent *e, gpointer data) {
20328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeJob *pj = data, *next;
20428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeScheduler *s;
20528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiDnsPacket *p;
20628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    guint n;
20728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
20828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(pj);
20928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    s = pj->scheduler;
21028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
2114ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if (pj->done) {
2124ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        /* Lets remove it  from the history */
2134ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        job_free(s, pj);
2144ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        return;
2154ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    }
2164ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
21728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    p = avahi_dns_packet_new_query(s->interface->hardware->mtu);
21828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    n = 1;
21928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
22028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Add the import probe */
22128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    if (!packet_add_probe_query(s, p, pj)) {
22228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        guint size;
22328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        AvahiKey *k;
22428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        gboolean b;
22528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
22628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        avahi_dns_packet_free(p);
22728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
22828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        /* The probe didn't fit in the package, so let's allocate a larger one */
22928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
23028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        size =
23128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            avahi_key_get_estimate_size(pj->record->key) +
23228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            avahi_record_get_estimate_size(pj->record) +
23328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            AVAHI_DNS_PACKET_HEADER_SIZE;
23428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
23528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (size > AVAHI_DNS_PACKET_MAX_SIZE)
23628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            size = AVAHI_DNS_PACKET_MAX_SIZE;
23728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
23828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        p = avahi_dns_packet_new_query(size);
23928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
24028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        k = avahi_key_new(pj->record->key->name, pj->record->key->class, AVAHI_DNS_TYPE_ANY);
24128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        b = avahi_dns_packet_append_key(p, k, FALSE) && avahi_dns_packet_append_record(p, pj->record, FALSE, 0);
24228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        avahi_key_unref(k);
24328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
24428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (b) {
24528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_NSCOUNT, 1);
24628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_QDCOUNT, 1);
24728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            avahi_interface_send_packet(s->interface, p);
24828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        } else
24928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            g_warning("Probe record too large, cannot send");
25028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
25128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        avahi_dns_packet_free(p);
2524ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        job_mark_done(s, pj);
25328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
25428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        return;
25528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    }
25628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
25728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Try to fill up packet with more probes, if available */
25828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    for (pj = s->jobs; pj; pj = pj->jobs_next) {
25928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
26028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (pj->chosen)
26128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            continue;
26228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
26328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (!packet_add_probe_query(s, p, pj))
26428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            break;
26528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
26628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        n++;
26728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    }
26828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
26928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_QDCOUNT, n);
27028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
27128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    n = 0;
27228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
27328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Now add the chosen records to the authorative section */
27428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    for (pj = s->jobs; pj; pj = next) {
27528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
27628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        next = pj->jobs_next;
27728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
27828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (!pj->chosen)
27928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            continue;
28028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
28128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (!avahi_dns_packet_append_record(p, pj->record, FALSE, 0)) {
28228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            g_warning("Bad probe size estimate!");
28328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
28428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            /* Unmark all following jobs */
28528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            for (; pj; pj = pj->jobs_next)
28628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering                pj->chosen = FALSE;
28728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
28828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            break;
28928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        }
29028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
2914ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        job_mark_done(s, pj);
29228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
29328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        n ++;
29428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    }
29528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
29628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_NSCOUNT, n);
29728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
29828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Send it now */
29928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_interface_send_packet(s->interface, p);
30028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_dns_packet_free(p);
30128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
30228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3034ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poetteringstatic AvahiProbeJob* find_scheduled_job(AvahiProbeScheduler *s, AvahiRecord *record) {
3044ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AvahiProbeJob *pj;
3054ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3064ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    g_assert(s);
3074ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    g_assert(record);
3084ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3094ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    for (pj = s->jobs; pj; pj = pj->jobs_next) {
3104ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        g_assert(!pj->done);
3114ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3124ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        if (avahi_record_equal_no_ttl(pj->record, record))
3134ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            return pj;
3144ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    }
3154ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3164ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    return NULL;
3174ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering}
3184ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3194ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poetteringstatic AvahiProbeJob* find_history_job(AvahiProbeScheduler *s, AvahiRecord *record) {
3204ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AvahiProbeJob *pj;
3214ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3224ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    g_assert(s);
3234ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    g_assert(record);
3244ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3254ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    for (pj = s->history; pj; pj = pj->jobs_next) {
3264ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        g_assert(pj->done);
3274ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3284ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        if (avahi_record_equal_no_ttl(pj->record, record)) {
3294ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            /* Check whether this entry is outdated */
3304ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3314ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            if (avahi_age(&pj->delivery) > AVAHI_PROBE_HISTORY_MSEC*1000) {
3324ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering                /* it is outdated, so let's remove it */
3334ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering                job_free(s, pj);
3344ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering                return NULL;
3354ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            }
3364ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3374ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            return pj;
3384ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        }
3394ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    }
3404ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3414ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    return NULL;
3424ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering}
3434ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
34428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringgboolean avahi_probe_scheduler_post(AvahiProbeScheduler *s, AvahiRecord *record, gboolean immediately) {
34528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeJob *pj;
34628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    GTimeVal tv;
34728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
34828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(s);
34928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(record);
35028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    g_assert(!avahi_key_is_pattern(record->key));
3514ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3524ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if ((pj = find_history_job(s, record)))
3534ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        return FALSE;
35428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
35528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_elapse_time(&tv, immediately ? 0 : AVAHI_PROBE_DEFER_MSEC, 0);
35628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3574ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if ((pj = find_scheduled_job(s, record))) {
3584ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3594ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        if (avahi_timeval_compare(&tv, &pj->delivery) < 0) {
3604ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            /* If the new entry should be scheduled earlier, update the old entry */
3614ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            pj->delivery = tv;
3624ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            avahi_time_event_queue_update(s->time_event_queue, pj->time_event, &pj->delivery);
3634ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        }
3644ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3654ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        return TRUE;
3664ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    } else {
3674ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        /* Create a new job and schedule it */
3684ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        pj = job_new(s, record, FALSE);
3694ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        pj->delivery = tv;
3704ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        pj->time_event = avahi_time_event_queue_add(s->time_event_queue, &pj->delivery, elapse_callback, pj);
37128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3724ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3734de3df3db7df43474176533d0b5fac851dd4a9b4Lennart Poettering/*     g_message("Accepted new probe job."); */
37428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3754ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        return TRUE;
3764ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    }
37728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
378