+
+void flx_server_add_text(flxServer *s, gint id, gint interface, guchar protocol, const gchar *name, const gchar *text) {
+ gchar *n;
+ g_assert(s);
+ g_assert(text);
+
+ n = flx_normalize_name(name ? name : s->hostname);
+ flx_server_add(s, id, interface, protocol, n, FLX_DNS_TYPE_TXT, text, strlen(text));
+ g_free(n);
+}
+
+
+flxQueryJob* flx_query_job_new(void) {
+ flxQueryJob *job = g_new(flxQueryJob, 1);
+ job->query.name = NULL;
+ job->query.class = 0;
+ job->query.type = 0;
+ job->ref = 1;
+ job->time.tv_sec = 0;
+ job->time.tv_usec = 0;
+ return job;
+}
+
+flxQueryJob* flx_query_job_ref(flxQueryJob *job) {
+ g_assert(job);
+ g_assert(job->ref >= 1);
+ job->ref++;
+ return job;
+}
+
+void flx_query_job_unref(flxQueryJob *job) {
+ g_assert(job);
+ g_assert(job->ref >= 1);
+ if (!(--job->ref))
+ g_free(job);
+}
+
+static gboolean query_job_exists(flxServer *s, gint interface, guchar protocol, flxQuery *q) {
+ flxPrioQueueNode *n;
+ g_assert(s);
+ g_assert(q);
+
+ for (n = s->query_job_queue->root; n; n = n->next)
+ if (flx_query_equal(&((flxQueryJobInstance*) n->data)->job->query, q))
+ return TRUE;
+
+ return FALSE;
+}
+
+static void post_query_job(flxServer *s, gint interface, guchar protocol, flxQueryJob *job) {
+ g_assert(s);
+ g_assert(job);
+
+ if (interface <= 0) {
+ const flxInterface *i;
+
+ for (i = flx_interface_monitor_get_first(s->monitor); i; i = i->next)
+ post_query_job(s, i->index, protocol, job);
+ } else if (protocol == AF_UNSPEC) {
+ post_query_job(s, interface, AF_INET, job);
+ post_query_job(s, interface, AF_INET6, job);
+ } else {
+ flxQueryJobInstance *i;
+
+ if (query_job_exists(s, interface, protocol, &job->query))
+ return;
+
+ i = g_new(flxQueryJobInstance, 1);
+ i->job = flx_query_job_ref(job);
+ i->interface = interface;
+ i->protocol = protocol;
+ i->node = flx_prio_queue_put(s->query_job_queue, i);
+ }
+}
+
+void flx_server_post_query_job(flxServer *s, gint interface, guchar protocol, const GTimeVal *tv, const flxQuery *q) {
+ flxQueryJob *job;
+ g_assert(s);
+ g_assert(q);
+
+ job = flx_query_job_new();
+ job->query.name = g_strdup(q->name);
+ job->query.class = q->class;
+ job->query.type = q->type;
+ if (tv)
+ job->time = *tv;
+ post_query_job(s, interface, protocol, job);
+}
+
+void flx_server_drop_query_job(flxServer *s, gint interface, guchar protocol, const flxQuery *q) {
+ flxPrioQueueNode *n, *next;
+ g_assert(s);
+ g_assert(interface > 0);
+ g_assert(protocol != AF_UNSPEC);
+ g_assert(q);
+
+ for (n = s->query_job_queue->root; n; n = next) {
+ next = n->next;
+
+ if (flx_query_equal(&((flxQueryJobInstance*) n->data)->job->query, q))
+ flx_server_remove_query_job_instance(s, n->data);
+ }
+}
+
+void flx_server_remove_query_job_instance(flxServer *s, flxQueryJobInstance *i) {
+ g_assert(s);
+ g_assert(i);
+ g_assert(i->node);
+
+ flx_prio_queue_remove(s->query_job_queue, i->node);
+ flx_query_job_unref(i->job);
+ g_free(i);
+}
+
+gboolean flx_query_equal(const flxQuery *a, const flxQuery *b) {
+ return strcmp(a->name, b->name) == 0 && a->type == b->type && a->class == b->class;
+}
+