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; }
void avahi_response_scheduler_suppress(AvahiResponseScheduler *s, AvahiRecord *record, const AvahiAddress *querier) { AvahiResponseJob *rj; assert(s); assert(record); assert(querier); if ((rj = find_scheduled_job(s, record))) { if (rj->querier_valid && avahi_address_cmp(querier, &rj->querier) == 0 && /* same originator */ avahi_record_is_goodbye(record) == avahi_record_is_goodbye(rj->record) && /* both goodbye packets, or both not */ record->ttl >= rj->record->ttl/2) { /* sensible TTL */ /* A matching entry was found, so let's drop it */ /* avahi_log_debug("Known answer suppression active!"); */ job_free(s, rj); } } if ((rj = find_suppressed_job(s, record, querier))) { /* Let's update the old entry */ avahi_record_unref(rj->record); rj->record = avahi_record_ref(record); } else { /* Create a new entry */ if (!(rj = job_new(s, record, AVAHI_SUPPRESSED))) return; /* OOM */ rj->querier_valid = 1; rj->querier = *querier; } gettimeofday(&rj->delivery, NULL); job_set_elapse_time(s, rj, AVAHI_RESPONSE_SUPPRESS_MSEC, 0); }
void avahi_response_scheduler_incoming(AvahiResponseScheduler *s, AvahiRecord *record, int flush_cache) { AvahiResponseJob *rj; assert(s); /* This function is called whenever an incoming response was * receieved. We drop scheduled responses which match here. The * keyword is "DUPLICATE ANSWER SUPPRESION". */ if ((rj = find_scheduled_job(s, record))) { if ((!rj->flush_cache || flush_cache) && /* flush cache bit was set correctly */ avahi_record_is_goodbye(record) == avahi_record_is_goodbye(rj->record) && /* both goodbye packets, or both not */ record->ttl >= rj->record->ttl/2) { /* sensible TTL */ /* A matching entry was found, so let's mark it done */ /* avahi_log_debug("Response suppressed by distributed duplicate suppression"); */ job_mark_done(s, rj); } return; } if ((rj = find_history_job(s, record))) { /* Found a history job, let's update it */ avahi_record_unref(rj->record); rj->record = avahi_record_ref(record); } else /* Found no existing history job, so let's create a new one */ if (!(rj = job_new(s, record, AVAHI_DONE))) return; /* OOM */ rj->flush_cache = flush_cache; rj->querier_valid = 0; gettimeofday(&rj->delivery, NULL); job_set_elapse_time(s, rj, AVAHI_RESPONSE_HISTORY_MSEC, 0); }
void avahi_query_scheduler_incoming(AvahiQueryScheduler *s, AvahiKey *key) { AvahiQueryJob *qj; assert(s); assert(key); /* This function is called whenever an incoming query was * received. We drop scheduled queries that match. The keyword is * "DUPLICATE QUESTION SUPPRESION". */ if ((qj = find_scheduled_job(s, key))) { job_mark_done(s, qj); return; } /* Look if there's a history job for this key. If there is, just * update the elapse time */ if (!(qj = find_history_job(s, key))) if (!(qj = job_new(s, key, 1))) return; /* OOM */ gettimeofday(&qj->delivery, NULL); job_set_elapse_time(s, qj, AVAHI_QUERY_HISTORY_MSEC, 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; } }
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; } }