128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering/***
228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  This file is part of avahi.
3a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  avahi is free software; you can redistribute it and/or modify it
528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  under the terms of the GNU Lesser General Public License as
628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  published by the Free Software Foundation; either version 2.1 of the
728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  License, or (at your option) any later version.
8a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  avahi is distributed in the hope that it will be useful, but WITHOUT
1028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
1228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  Public License for more details.
13a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  You should have received a copy of the GNU Lesser General Public
1528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  License along with avahi; if not, write to the Free Software
1628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering  USA.
1828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering***/
1928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
2028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering#ifdef HAVE_CONFIG_H
2128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering#include <config.h>
2228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering#endif
2328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
24b4bb609c78d2f4ce834a60efccd876117f0753f6Lennart Poettering#include <stdlib.h>
25b4bb609c78d2f4ce834a60efccd876117f0753f6Lennart Poettering
265ebf655c85076f200955458673a8bbf0dd927407Lennart Poettering#include <avahi-common/domain.h>
275d047523c87ba11aad8c384f7ffde25b4dd746edLennart Poettering#include <avahi-common/timeval.h>
288e46e738cae449bf44232c66e973c8e9e15fbcb5Robert Ginda#include "avahi-common/avahi-malloc.h"
295ebf655c85076f200955458673a8bbf0dd927407Lennart Poettering
3028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering#include "probe-sched.h"
31c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering#include "log.h"
326efe2615e04c6ef664fa9d49b013e261ba1e6e66Lennart Poettering#include "rr-util.h"
3328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
344ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering#define AVAHI_PROBE_HISTORY_MSEC 150
354ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering#define AVAHI_PROBE_DEFER_MSEC 50
3628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringtypedef struct AvahiProbeJob AvahiProbeJob;
3828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringstruct AvahiProbeJob {
4028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeScheduler *scheduler;
4128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiTimeEvent *time_event;
42a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
434f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    int chosen; /* Use for packet assembling */
444f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    int done;
45e63a65b3955b173a3e8d6b78c6377a518a9922d6Lennart Poettering    struct timeval delivery;
4628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
4728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiRecord *record;
48a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
4928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AVAHI_LLIST_FIELDS(AvahiProbeJob, jobs);
5028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering};
5128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
5228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringstruct AvahiProbeScheduler {
5328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiInterface *interface;
5428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiTimeEventQueue *time_event_queue;
5528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
5628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AVAHI_LLIST_HEAD(AvahiProbeJob, jobs);
574ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AVAHI_LLIST_HEAD(AvahiProbeJob, history);
5828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering};
5928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
604f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringstatic AvahiProbeJob* job_new(AvahiProbeScheduler *s, AvahiRecord *record, int done) {
6128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeJob *pj;
62a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
634f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
644f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(record);
6528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
664f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(pj = avahi_new(AvahiProbeJob, 1))) {
674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        avahi_log_error(__FILE__": Out of memory");
684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL; /* OOM */
694f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    }
70a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
7128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    pj->scheduler = s;
7228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    pj->record = avahi_record_ref(record);
7328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    pj->time_event = NULL;
744f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    pj->chosen = 0;
754ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
764ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if ((pj->done = done))
774ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        AVAHI_LLIST_PREPEND(AvahiProbeJob, jobs, s->history, pj);
784ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    else
794ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        AVAHI_LLIST_PREPEND(AvahiProbeJob, jobs, s->jobs, pj);
8028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
8128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    return pj;
8228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
8328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
8428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringstatic void job_free(AvahiProbeScheduler *s, AvahiProbeJob *pj) {
854f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(pj);
8628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
8728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    if (pj->time_event)
884f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        avahi_time_event_free(pj->time_event);
8928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
904ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if (pj->done)
914ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        AVAHI_LLIST_REMOVE(AvahiProbeJob, jobs, s->history, pj);
924ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    else
934ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        AVAHI_LLIST_REMOVE(AvahiProbeJob, jobs, s->jobs, pj);
9428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
9528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_record_unref(pj->record);
964f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    avahi_free(pj);
9728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
9828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
994f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringstatic void elapse_callback(AvahiTimeEvent *e, void* data);
1004ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1014f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringstatic void job_set_elapse_time(AvahiProbeScheduler *s, AvahiProbeJob *pj, unsigned msec, unsigned jitter) {
102e63a65b3955b173a3e8d6b78c6377a518a9922d6Lennart Poettering    struct timeval tv;
1034ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1044f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
1054f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(pj);
1064ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1074ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    avahi_elapse_time(&tv, msec, jitter);
1084ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1094ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if (pj->time_event)
1104f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        avahi_time_event_update(pj->time_event, &tv);
1114ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    else
1124f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        pj->time_event = avahi_time_event_new(s->time_event_queue, &tv, elapse_callback, pj);
1134ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering}
1144ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1154ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poetteringstatic void job_mark_done(AvahiProbeScheduler *s, AvahiProbeJob *pj) {
1164f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
1174f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(pj);
1184ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1194f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(!pj->done);
1204ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1214ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AVAHI_LLIST_REMOVE(AvahiProbeJob, jobs, s->jobs, pj);
1224ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AVAHI_LLIST_PREPEND(AvahiProbeJob, jobs, s->history, pj);
1234ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1244f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    pj->done = 1;
1254ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
1264ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    job_set_elapse_time(s, pj, AVAHI_PROBE_HISTORY_MSEC, 0);
127e63a65b3955b173a3e8d6b78c6377a518a9922d6Lennart Poettering    gettimeofday(&pj->delivery, NULL);
1284ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering}
12928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
13028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart PoetteringAvahiProbeScheduler *avahi_probe_scheduler_new(AvahiInterface *i) {
13128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeScheduler *s;
13228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
1334f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(i);
13428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
1354f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(s = avahi_new(AvahiProbeScheduler, 1))) {
1364f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        avahi_log_error(__FILE__": Out of memory");
1374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
1384f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    }
139a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
14028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    s->interface = i;
14128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    s->time_event_queue = i->monitor->server->time_event_queue;
14228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
14328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AVAHI_LLIST_HEAD_INIT(AvahiProbeJob, s->jobs);
1444ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AVAHI_LLIST_HEAD_INIT(AvahiProbeJob, s->history);
145a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
14628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    return s;
14728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
14828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
14928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringvoid avahi_probe_scheduler_free(AvahiProbeScheduler *s) {
1504f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
15128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
15228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_probe_scheduler_clear(s);
1534f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    avahi_free(s);
15428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
15528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
15628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poetteringvoid avahi_probe_scheduler_clear(AvahiProbeScheduler *s) {
1574f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
158a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
15928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    while (s->jobs)
16028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        job_free(s, s->jobs);
1614ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    while (s->history)
1624ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        job_free(s, s->history);
16328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
164a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1654f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringstatic int packet_add_probe_query(AvahiProbeScheduler *s, AvahiDnsPacket *p, AvahiProbeJob *pj) {
1664f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t size;
16728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiKey *k;
1684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    int b;
16928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
1704f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
1714f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1724f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(pj);
17328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
1744f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(!pj->chosen);
175a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
17628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Estimate the size for this record */
17728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    size =
17828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        avahi_key_get_estimate_size(pj->record->key) +
17928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        avahi_record_get_estimate_size(pj->record);
18028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
18128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Too large */
18228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    if (size > avahi_dns_packet_space(p))
1834f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return 0;
18428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
18528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Create the probe query */
1864f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(k = avahi_key_new(pj->record->key->name, pj->record->key->clazz, AVAHI_DNS_TYPE_ANY)))
1874f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return 0; /* OOM */
188a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1894f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    b = !!avahi_dns_packet_append_key(p, k, 0);
1904f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(b);
19128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
19228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Mark this job for addition to the packet */
1934f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    pj->chosen = 1;
19428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
19528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Scan for more jobs whith matching key pattern */
19628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    for (pj = s->jobs; pj; pj = pj->jobs_next) {
19728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (pj->chosen)
19828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            continue;
19928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
20028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        /* Does the record match the probe? */
20114f8d9beb7ef14b0aab5512345e09109bdd8cb0cLennart Poettering        if (k->clazz != pj->record->key->clazz || !avahi_domain_equal(k->name, pj->record->key->name))
20228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            continue;
203a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
20428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        /* This job wouldn't fit in */
20528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (avahi_record_get_estimate_size(pj->record) > avahi_dns_packet_space(p))
20628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            break;
20728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
20828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        /* Mark this job for addition to the packet */
2094f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        pj->chosen = 1;
21028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    }
21128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
21228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_key_unref(k);
213a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
2144f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    return 1;
21528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
21628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
217854f901f491ccda79aee11edc3d59109cb229d28Lennart Poetteringstatic void elapse_callback(AVAHI_GCC_UNUSED AvahiTimeEvent *e, void* data) {
21828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeJob *pj = data, *next;
21928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeScheduler *s;
22028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiDnsPacket *p;
2214f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    unsigned n;
22228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
2234f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(pj);
22428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    s = pj->scheduler;
22528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
2264ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if (pj->done) {
2274ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        /* Lets remove it  from the history */
2284ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        job_free(s, pj);
2294ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        return;
2304ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    }
2314ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
2324f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_dns_packet_new_query(s->interface->hardware->mtu)))
2334f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return; /* OOM */
23428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    n = 1;
235a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
23628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Add the import probe */
23728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    if (!packet_add_probe_query(s, p, pj)) {
2384f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        size_t size;
23928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        AvahiKey *k;
2404f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        int b;
24128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
24228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        avahi_dns_packet_free(p);
24328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
24428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        /* The probe didn't fit in the package, so let's allocate a larger one */
24528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
24628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        size =
24728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            avahi_key_get_estimate_size(pj->record->key) +
24828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            avahi_record_get_estimate_size(pj->record) +
24928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            AVAHI_DNS_PACKET_HEADER_SIZE;
250a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
251bbf6b92f662ed909d5b4fca4a43b19e815812b3eLennart Poettering        if (!(p = avahi_dns_packet_new_query(size + AVAHI_DNS_PACKET_EXTRA_SIZE)))
2524f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            return; /* OOM */
2534f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
2544f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        if (!(k = avahi_key_new(pj->record->key->name, pj->record->key->clazz, AVAHI_DNS_TYPE_ANY))) {
2554f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            avahi_dns_packet_free(p);
2564f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            return;  /* OOM */
2574f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        }
258a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
2594f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        b = avahi_dns_packet_append_key(p, k, 0) && avahi_dns_packet_append_record(p, pj->record, 0, 0);
26028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        avahi_key_unref(k);
26128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
26228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (b) {
26328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_NSCOUNT, 1);
26428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_QDCOUNT, 1);
26528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            avahi_interface_send_packet(s->interface, p);
26628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        } else
267a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering            avahi_log_warn("Probe record too large, cannot send");
268a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
26928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        avahi_dns_packet_free(p);
2704ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        job_mark_done(s, pj);
27128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
27228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        return;
27328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    }
27428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
27528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Try to fill up packet with more probes, if available */
27628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    for (pj = s->jobs; pj; pj = pj->jobs_next) {
27728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
27828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (pj->chosen)
27928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            continue;
280a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
28128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (!packet_add_probe_query(s, p, pj))
28228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            break;
283a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
28428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        n++;
28528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    }
28628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
28728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_QDCOUNT, n);
28828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
28928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    n = 0;
29028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
29128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Now add the chosen records to the authorative section */
29228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    for (pj = s->jobs; pj; pj = next) {
29328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
29428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        next = pj->jobs_next;
29528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
29628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        if (!pj->chosen)
29728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            continue;
29828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
2994f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        if (!avahi_dns_packet_append_record(p, pj->record, 0, 0)) {
300a3737cc61b48d7d435aadb573d3ef58e0849bf3dLennart Poettering/*             avahi_log_warn("Bad probe size estimate!"); */
30128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
30228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            /* Unmark all following jobs */
30328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            for (; pj; pj = pj->jobs_next)
3044f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering                pj->chosen = 0;
305a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
30628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering            break;
30728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        }
30828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3094ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        job_mark_done(s, pj);
310a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
31128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering        n ++;
31228d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    }
313a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
31428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_NSCOUNT, n);
31528d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
31628d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    /* Send it now */
31728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_interface_send_packet(s->interface, p);
31828d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_dns_packet_free(p);
31928d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
32028d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3214ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poetteringstatic AvahiProbeJob* find_scheduled_job(AvahiProbeScheduler *s, AvahiRecord *record) {
3224ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AvahiProbeJob *pj;
3234ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3244f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
3254f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(record);
3264ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3274ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    for (pj = s->jobs; pj; pj = pj->jobs_next) {
3284f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        assert(!pj->done);
329a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3304ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        if (avahi_record_equal_no_ttl(pj->record, record))
3314ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            return pj;
3324ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    }
3334ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3344ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    return NULL;
3354ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering}
3364ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3374ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poetteringstatic AvahiProbeJob* find_history_job(AvahiProbeScheduler *s, AvahiRecord *record) {
3384ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    AvahiProbeJob *pj;
339a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3404f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
3414f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(record);
3424ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3434ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    for (pj = s->history; pj; pj = pj->jobs_next) {
3444f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        assert(pj->done);
3454ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3464ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        if (avahi_record_equal_no_ttl(pj->record, record)) {
3474ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            /* Check whether this entry is outdated */
3484ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3494ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            if (avahi_age(&pj->delivery) > AVAHI_PROBE_HISTORY_MSEC*1000) {
3504ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering                /* it is outdated, so let's remove it */
3514ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering                job_free(s, pj);
3524ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering                return NULL;
3534ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            }
354a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3554ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            return pj;
3564ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        }
3574ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    }
3584ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3594ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    return NULL;
3604ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering}
3614ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3624f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_probe_scheduler_post(AvahiProbeScheduler *s, AvahiRecord *record, int immediately) {
36328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    AvahiProbeJob *pj;
364e63a65b3955b173a3e8d6b78c6377a518a9922d6Lennart Poettering    struct timeval tv;
365a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3664f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
3674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(record);
3684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(!avahi_key_is_pattern(record->key));
3694ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3704ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if ((pj = find_history_job(s, record)))
3714f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return 0;
37248cfb3c876636d79dace3ebc8e82c946bc0b7ebfLennart Poettering
37328d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering    avahi_elapse_time(&tv, immediately ? 0 : AVAHI_PROBE_DEFER_MSEC, 0);
37428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3754ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    if ((pj = find_scheduled_job(s, record))) {
3764ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3774ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        if (avahi_timeval_compare(&tv, &pj->delivery) < 0) {
3784ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            /* If the new entry should be scheduled earlier, update the old entry */
3794ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering            pj->delivery = tv;
3804f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            avahi_time_event_update(pj->time_event, &pj->delivery);
3814ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        }
3824ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering
3834f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return 1;
3844ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    } else {
3854ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        /* Create a new job and schedule it */
3864f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        if (!(pj = job_new(s, record, 0)))
3874f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            return 0; /* OOM */
388a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3894ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering        pj->delivery = tv;
3904f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        pj->time_event = avahi_time_event_new(s->time_event_queue, &pj->delivery, elapse_callback, pj);
39128d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
392a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
393c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*     avahi_log_debug("Accepted new probe job."); */
39428d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering
3954f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return 1;
3964ff0807c04fcc239de52a793bceb88e7f3408f3fLennart Poettering    }
39728d336020ca1f6dbb88d64cac3ffdd1a67ee3de7Lennart Poettering}
398