From a3d45b39608418e261f34b3b3286b80e4878d25c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 16 Nov 2005 01:15:46 +0000 Subject: [PATCH] * when calculating a random jitter time for time events, use the same jitter in every 10s timespans. This should increase the probability that multiple responses can be merged into a single packet, and thus decreases network traffic. * add _workstation._tcp services in RUNNING state, not earlier * an important bugfix which fixes the entry group state automatons * remove obsolete debug messages * minor other cleanups git-svn-id: file:///home/lennart/svn/public/avahi/trunk@980 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- avahi-common/timeval.c | 30 +++++++++++++++++++++++++++--- avahi-core/announce.c | 28 ++-------------------------- avahi-core/cache.c | 13 ++++++++++++- avahi-core/cache.h | 3 +++ avahi-core/entry.c | 15 ++++++--------- avahi-core/iface.c | 23 ++++------------------- avahi-core/internal.h | 1 - avahi-core/server.c | 15 ++------------- avahi-core/util.c | 23 ++++++++++++++++------- avahi-core/util.h | 2 +- 10 files changed, 73 insertions(+), 80 deletions(-) diff --git a/avahi-common/timeval.c b/avahi-common/timeval.c index e5732cd..2d0d693 100644 --- a/avahi-common/timeval.c +++ b/avahi-common/timeval.c @@ -23,6 +23,7 @@ #include #endif +#include #include #include @@ -84,7 +85,6 @@ AvahiUsec avahi_age(const struct timeval *a) { return avahi_timeval_diff(&now, a); } - struct timeval *avahi_elapse_time(struct timeval *tv, unsigned msec, unsigned jitter) { assert(tv); @@ -93,8 +93,32 @@ struct timeval *avahi_elapse_time(struct timeval *tv, unsigned msec, unsigned ji if (msec) avahi_timeval_add(tv, (AvahiUsec) msec*1000); - if (jitter) - avahi_timeval_add(tv, (AvahiUsec) (jitter*1000.0*rand()/(RAND_MAX+1.0))); + if (jitter) { + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + static int last_rand; + static time_t timestamp = 0; + + time_t now; + int r; + + now = time(NULL); + + pthread_mutex_lock(&mutex); + if (now >= timestamp + 10) { + timestamp = now; + last_rand = rand(); + } + + r = last_rand; + + pthread_mutex_unlock(&mutex); + + /* We use the same jitter for 10 seconds. That way our + * time events elapse in bursts which has the advantage that + * packet data can be aggegrated better */ + + avahi_timeval_add(tv, (AvahiUsec) (jitter*1000.0*r/(RAND_MAX+1.0))); + } return tv; } diff --git a/avahi-core/announce.c b/avahi-core/announce.c index 061f104..b66dada 100644 --- a/avahi-core/announce.c +++ b/avahi-core/announce.c @@ -83,11 +83,11 @@ void avahi_s_entry_group_check_probed(AvahiSEntryGroup *g, int immediately) { if (g->dead) return; - for (e = g->entries; e; e = e->entries_next) { + for (e = g->entries; e; e = e->by_group_next) { AvahiAnnouncer *a; for (a = e->announcers; a; a = a->by_entry_next) { - + if (a->state != AVAHI_WAITING) continue; @@ -111,8 +111,6 @@ void avahi_s_entry_group_check_probed(AvahiSEntryGroup *g, int immediately) { static void next_state(AvahiAnnouncer *a) { assert(a); -/* avahi_log_debug("%i -- %u", a->state, a->n_iteration); */ - if (a->state == AVAHI_WAITING) { assert(a->entry->group); @@ -124,11 +122,6 @@ static void next_state(AvahiAnnouncer *a) { if (a->n_iteration >= 4) { /* Probing done */ -/* char *t; */ - -/* avahi_log_debug("Enough probes for record [%s]", t = avahi_record_to_string(a->entry->record)); */ -/* avahi_free(t); */ - if (a->entry->group) { assert(a->entry->group->n_probing); a->entry->group->n_probing--; @@ -165,12 +158,8 @@ static void next_state(AvahiAnnouncer *a) { avahi_server_generate_response(a->server, a->interface, NULL, NULL, 0, 0, 0); if (++a->n_iteration >= 4) { -/* char *t; */ /* Announcing done */ -/* avahi_log_debug("Enough announcements for record [%s]", t = avahi_record_to_string(a->entry->record)); */ -/* avahi_free(t); */ - a->state = AVAHI_ESTABLISHED; set_timeout(a, NULL); @@ -241,16 +230,12 @@ static void go_to_initial_state(AvahiAnnouncer *a) { static void new_announcer(AvahiServer *s, AvahiInterface *i, AvahiEntry *e) { AvahiAnnouncer *a; -/* char *t; */ assert(s); assert(i); assert(e); assert(!e->dead); -/* avahi_log_debug("NEW ANNOUNCER: %s.%i [%s]", i->hardware->name, i->protocol, t = avahi_record_to_string(e->record)); */ -/* avahi_free(t); */ - if (!avahi_interface_match(i, e->interface, e->protocol) || !i->announcing || !avahi_entry_is_commited(e)) return; @@ -272,9 +257,6 @@ static void new_announcer(AvahiServer *s, AvahiInterface *i, AvahiEntry *e) { AVAHI_LLIST_PREPEND(AvahiAnnouncer, by_entry, e->announcers, a); go_to_initial_state(a); - -/* avahi_log_debug("New announcer on interface %s.%i for entry [%s] state=%i", i->hardware->name, i->protocol, t = avahi_record_to_string(e->record), a->state); */ -/* avahi_free(t); */ } void avahi_announce_interface(AvahiServer *s, AvahiInterface *i) { @@ -348,8 +330,6 @@ int avahi_entry_is_probing(AvahiServer *s, AvahiEntry *e, AvahiInterface *i) { if (!(a = get_announcer(s, e, i))) return 0; - -/* avahi_log_debug("state: %i", a->state); */ return a->state == AVAHI_PROBING || @@ -373,14 +353,10 @@ void avahi_entry_return_to_initial_state(AvahiServer *s, AvahiEntry *e, AvahiInt } static AvahiRecord *make_goodbye_record(AvahiRecord *r) { -/* char *t; */ AvahiRecord *g; assert(r); -/* avahi_log_debug("Preparing goodbye for record [%s]", t = avahi_record_to_string(r)); */ -/* avahi_free(t); */ - if (!(g = avahi_record_copy(r))) return NULL; /* OOM */ diff --git a/avahi-core/cache.c b/avahi-core/cache.c index c26b6bb..3a8f849 100644 --- a/avahi-core/cache.c +++ b/avahi-core/cache.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -86,6 +87,8 @@ AvahiCache *avahi_cache_new(AvahiServer *server, AvahiInterface *iface) { AVAHI_LLIST_HEAD_INIT(AvahiCacheEntry, c->entries); c->n_entries = 0; + + c->last_rand_timestamp = 0; return c; } @@ -235,6 +238,7 @@ static void update_time_event(AvahiCache *c, AvahiCacheEntry *e) { static void next_expiry(AvahiCache *c, AvahiCacheEntry *e, unsigned percent) { AvahiUsec usec, left, right; + time_t now; assert(c); assert(e); @@ -245,7 +249,14 @@ static void next_expiry(AvahiCache *c, AvahiCacheEntry *e, unsigned percent) { left = usec * percent; right = usec * (percent+2); /* 2% jitter */ - usec = left + (AvahiUsec) ((double) (right-left) * rand() / (RAND_MAX+1.0)); + now = time(NULL); + + if (now >= c->last_rand_timestamp + 10) { + c->last_rand = rand(); + c->last_rand_timestamp = now; + } + + usec = left + (AvahiUsec) ((double) (right-left) * c->last_rand / (RAND_MAX+1.0)); e->expiry = e->timestamp; avahi_timeval_add(&e->expiry, usec); diff --git a/avahi-core/cache.h b/avahi-core/cache.h index 4fbc1b9..edf9fa5 100644 --- a/avahi-core/cache.h +++ b/avahi-core/cache.h @@ -72,6 +72,9 @@ struct AvahiCache { AVAHI_LLIST_HEAD(AvahiCacheEntry, entries); unsigned n_entries; + + int last_rand; + time_t last_rand_timestamp; }; AvahiCache *avahi_cache_new(AvahiServer *server, AvahiInterface *interface); diff --git a/avahi-core/entry.c b/avahi-core/entry.c index d294647..5baaf40 100644 --- a/avahi-core/entry.c +++ b/avahi-core/entry.c @@ -1083,18 +1083,17 @@ static void entry_group_commit_real(AvahiSEntryGroup *g) { avahi_s_entry_group_change_state(g, AVAHI_ENTRY_GROUP_REGISTERING); - if (!g->dead) { - avahi_announce_group(g->server, g); - avahi_s_entry_group_check_probed(g, 0); - } + if (g->dead) + return; + + avahi_announce_group(g->server, g); + avahi_s_entry_group_check_probed(g, 0); } static void entry_group_register_time_event_callback(AVAHI_GCC_UNUSED AvahiTimeEvent *e, void* userdata) { AvahiSEntryGroup *g = userdata; assert(g); -/* avahi_log_debug("Holdoff passed, waking up and going on."); */ - avahi_time_event_free(g->register_time_event); g->register_time_event = NULL; @@ -1121,12 +1120,10 @@ int avahi_s_entry_group_commit(AvahiSEntryGroup *g) { gettimeofday(&now, NULL); if (avahi_timeval_compare(&g->register_time, &now) <= 0) { - /* Holdoff time passed, so let's start probing */ -/* avahi_log_debug("Holdoff passed, directly going on."); */ + /* Holdoff time passed, so let's start probing */ entry_group_commit_real(g); } else { -/* avahi_log_debug("Holdoff not passed, sleeping."); */ /* Holdoff time has not yet passed, so let's wait */ assert(!g->register_time_event); diff --git a/avahi-core/iface.c b/avahi-core/iface.c index 0f4d518..c96f081 100644 --- a/avahi-core/iface.c +++ b/avahi-core/iface.c @@ -121,8 +121,7 @@ void avahi_hw_interface_update_rrs(AvahiHwInterface *hw, int remove_rrs) { if (m->list_complete && !remove_rrs && m->server->config.publish_workstation && - (m->server->state == AVAHI_SERVER_RUNNING || - m->server->state == AVAHI_SERVER_REGISTERING)) { + (m->server->state == AVAHI_SERVER_RUNNING)) { if (!hw->entry_group) hw->entry_group = avahi_s_entry_group_new(m->server, avahi_host_rr_entry_group_callback, NULL); @@ -131,18 +130,11 @@ void avahi_hw_interface_update_rrs(AvahiHwInterface *hw, int remove_rrs) { return; /* OOM */ if (avahi_s_entry_group_is_empty(hw->entry_group)) { - char name[AVAHI_LABEL_MAX]; - char *t; - - if (!(t = avahi_format_mac_address(hw->mac_address, hw->mac_address_size))) - return; /* OOM */ + char name[AVAHI_LABEL_MAX], mac[256]; - snprintf(name, sizeof(name), "%s [%s]", m->server->host_name, t); - avahi_free(t); + avahi_format_mac_address(mac, sizeof(mac), hw->mac_address, hw->mac_address_size); + snprintf(name, sizeof(name), "%s [%s]", m->server->host_name, mac); - if (!name) - return; /* OOM */ - if (avahi_server_add_service(m->server, hw->entry_group, hw->index, AVAHI_PROTO_UNSPEC, 0, name, "_workstation._tcp", NULL, NULL, 9, NULL) < 0) { avahi_log_warn(__FILE__": avahi_server_add_service() failed: %s", avahi_strerror(m->server->error)); avahi_s_entry_group_free(hw->entry_group); @@ -557,22 +549,15 @@ AvahiInterfaceAddress* avahi_interface_monitor_get_address(AvahiInterfaceMonitor return NULL; } - void avahi_interface_send_packet_unicast(AvahiInterface *i, AvahiDnsPacket *p, const AvahiAddress *a, uint16_t port) { assert(i); assert(p); -/* char t[AVAHI_ADDRESS_STR_MAX]; */ if (!avahi_interface_is_relevant(i)) return; assert(!a || a->proto == i->protocol); -/* if (a) */ -/* avahi_log_debug("unicast sending on '%s.%i' to %s:%u", i->hardware->name, i->protocol, avahi_address_snprint(t, sizeof(t), a), port); */ -/* else */ -/* avahi_log_debug("multicast sending on '%s.%i'", i->hardware->name, i->protocol); */ - if (i->protocol == AVAHI_PROTO_INET && i->monitor->server->fd_ipv4 >= 0) avahi_send_dns_packet_ipv4(i->monitor->server->fd_ipv4, i->hardware->index, p, i->mcast_joined ? &i->local_mcast_address.data.ipv4 : NULL, a ? &a->data.ipv4 : NULL, port); else if (i->protocol == AVAHI_PROTO_INET6 && i->monitor->server->fd_ipv6 >= 0) diff --git a/avahi-core/internal.h b/avahi-core/internal.h index c791d8d..0d88d5a 100644 --- a/avahi-core/internal.h +++ b/avahi-core/internal.h @@ -195,7 +195,6 @@ int avahi_server_add_ptr( const char *name, const char *dest); - #define AVAHI_CHECK_VALIDITY(server, expression, error) { \ if (!(expression)) \ return avahi_server_set_errno((server), (error)); \ diff --git a/avahi-core/server.c b/avahi-core/server.c index 28a9978..16626d7 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -560,8 +560,6 @@ static void handle_query_packet(AvahiServer *s, AvahiDnsPacket *p, AvahiInterfac assert(i); assert(a); -/* avahi_log_debug("query"); */ - assert(avahi_record_list_is_empty(s->record_list)); is_probe = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_NSCOUNT) > 0; @@ -649,8 +647,6 @@ static void handle_response_packet(AvahiServer *s, AvahiDnsPacket *p, AvahiInter assert(i); assert(a); -/* avahi_log_debug("response"); */ - for (n = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ANCOUNT) + avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ARCOUNT); n > 0; n--) { AvahiRecord *record; @@ -664,9 +660,6 @@ static void handle_response_packet(AvahiServer *s, AvahiDnsPacket *p, AvahiInter if (!avahi_key_is_pattern(record->key)) { -/* avahi_log_debug("Handling response: %s", txt = avahi_record_to_string(record)); */ -/* avahi_free(txt); */ - if (handle_conflict(s, i, record, cache_flush)) { if (!from_local_iface) reflect_response(s, i, record, cache_flush); @@ -785,8 +778,6 @@ static void reflect_legacy_unicast_query_packet(AvahiServer *s, AvahiDnsPacket * if (!s->config.enable_reflector) return; -/* avahi_log_debug("legacy unicast reflector"); */ - /* Reflecting legacy unicast queries is a little more complicated than reflecting normal queries, since we must route the responses back to the right client. Therefore we must store @@ -899,8 +890,6 @@ static void dispatch_packet(AvahiServer *s, AvahiDnsPacket *p, const AvahiAddres return; } -/* avahi_log_debug("new packet received on interface '%s.%i'.", i->hardware->name, i->protocol); */ - if (avahi_address_is_ipv4_in_ipv6(src_address)) /* This is an IPv4 address encapsulated in IPv6, so let's ignore it. */ return; @@ -943,7 +932,6 @@ static void dispatch_packet(AvahiServer *s, AvahiDnsPacket *p, const AvahiAddres handle_query_packet(s, p, i, src_address, port, legacy_unicast, from_local_iface); -/* avahi_log_debug("Handled query"); */ } else { if (port != AVAHI_MDNS_PORT) { avahi_log_warn("Recieved repsonse with invalid source port %u on interface '%s.%i'", port, i->hardware->name, i->protocol); @@ -969,7 +957,6 @@ static void dispatch_packet(AvahiServer *s, AvahiDnsPacket *p, const AvahiAddres } handle_response_packet(s, p, i, src_address, from_local_iface); -/* avahi_log_debug("Handled response"); */ } } @@ -1078,6 +1065,8 @@ static void server_set_state(AvahiServer *s, AvahiServerState state) { s->state = state; + avahi_interface_monitor_update_rrs(s->monitor, 0); + if (s->callback) s->callback(s, state, s->userdata); } diff --git a/avahi-core/util.c b/avahi-core/util.c index a5e9f52..b1925f0 100644 --- a/avahi-core/util.c +++ b/avahi-core/util.c @@ -66,29 +66,38 @@ void avahi_hexdump(const void* p, size_t size) { } } - -char *avahi_format_mac_address(const uint8_t* mac, size_t size) { - char *r, *t; +char *avahi_format_mac_address(char *r, size_t l, const uint8_t* mac, size_t size) { + char *t = r; unsigned i; static const char hex[] = "0123456789abcdef"; - if (!(t = r = avahi_new(char, size > 0 ? size*3 : 1))) - return NULL; - + assert(r); + assert(l > 0); + assert(mac); + if (size <= 0) { *r = 0; return r; } for (i = 0; i < size; i++) { + if (l < 3) + break; + *(t++) = hex[*mac >> 4]; *(t++) = hex[*mac & 0xF]; *(t++) = ':'; + l -= 3; + mac++; } - *(--t) = 0; + if (t > r) + *(t-1) = 0; + else + *r = 0; + return r; } diff --git a/avahi-core/util.h b/avahi-core/util.h index 1a07363..8d2caee 100644 --- a/avahi-core/util.h +++ b/avahi-core/util.h @@ -30,7 +30,7 @@ AVAHI_C_DECL_BEGIN void avahi_hexdump(const void *p, size_t size); -char *avahi_format_mac_address(const uint8_t* mac, size_t size); +char *avahi_format_mac_address(char *t, size_t l, const uint8_t* mac, size_t size); /** Change every character in the string to upper case (ASCII), return a pointer to the string */ char *avahi_strup(char *s); -- 2.39.5