X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=announce.c;h=d1b56657327a06c8612d58eb604f6c5708bdbaee;hb=ba8547ee3f34d8fe7bedb559530b2c0374f2089c;hp=9229753d9051beb9a78153f0038ddab9740413c3;hpb=cfc653d0fd2f58ef3f4b5ecb285d5beb5bfaacfb;p=catta diff --git a/announce.c b/announce.c index 9229753..d1b5665 100644 --- a/announce.c +++ b/announce.c @@ -15,69 +15,116 @@ static void remove_announcement(flxServer *s, flxAnnouncement *a) { g_free(a); } -static void elapse_announce(flxTimeEvent *e, void *userdata) { - flxAnnouncement *a = userdata; +static void elapse_announce(flxTimeEvent *e, void *userdata); + +static void send_packet(flxAnnouncement *a) { GTimeVal tv; - gchar *t; - - g_assert(e); g_assert(a); - flx_interface_post_response(a->interface, NULL, a->entry->record, FALSE); +/* g_message("%i -- %u", a->state, a->n_iteration); */ + + if (a->state == FLX_PROBING && a->n_iteration >= 1) { + flx_interface_post_probe(a->interface, a->entry->record, FALSE); + } else if (a->state == FLX_ANNOUNCING && a->n_iteration >= 1) + flx_interface_post_response(a->interface, NULL, a->entry->record, a->entry->flags & FLX_SERVER_ENTRY_UNIQUE, TRUE); + + a->n_iteration++; - if (a->n_announced++ <= 8) - a->sec_delay *= 2; + if (a->state == FLX_PROBING) { - g_message("Announcement #%i on interface %s.%i for entry [%s]", a->n_announced, a->interface->hardware->name, a->interface->protocol, t = flx_record_to_string(a->entry->record)); - g_free(t); + if (a->n_iteration == 1) + flx_elapse_time(&tv, 0, 250); + else + flx_elapse_time(&tv, 250, 0); + + /* Probing done */ + if (a->n_iteration >= 4) { + gchar *t; + g_message("Enough probes for record [%s]", t = flx_record_to_string(a->entry->record)); + g_free(t); + a->state = FLX_ANNOUNCING; + a->n_iteration = 1; + } + + } else if (a->state == FLX_ANNOUNCING) { - if (a->n_announced >= 4) { - g_message("Enough announcements for record [%s]", t = flx_record_to_string(a->entry->record)); - g_free(t); - remove_announcement(a->server, a); - } else { flx_elapse_time(&tv, a->sec_delay*1000, FLX_ANNOUNCEMENT_JITTER_MSEC); - flx_time_event_queue_update(a->server->time_event_queue, a->time_event, &tv); + + if (a->n_iteration < 10) + a->sec_delay *= 2; + + /* Announcing done */ + if (a->n_iteration >= 4) { + gchar *t; + g_message("Enough announcements for record [%s]", t = flx_record_to_string(a->entry->record)); + g_free(t); + remove_announcement(a->server, a); + return; + } } + + if (a->time_event) + flx_time_event_queue_update(a->server->time_event_queue, a->time_event, &tv); + else + a->time_event = flx_time_event_queue_add(a->server->time_event_queue, &tv, elapse_announce, a); +} + +static void elapse_announce(flxTimeEvent *e, void *userdata) { + g_assert(e); + + send_packet(userdata); +} + +static flxAnnouncement *get_announcement(flxServer *s, flxServerEntry *e, flxInterface *i) { + flxAnnouncement *a; + + g_assert(s); + g_assert(e); + g_assert(i); + + for (a = e->announcements; a; a = a->by_entry_next) + if (a->interface == i) + return a; + + return NULL; } static void new_announcement(flxServer *s, flxInterface *i, flxServerEntry *e) { flxAnnouncement *a; GTimeVal tv; - gchar *t; + gchar *t; g_assert(s); g_assert(i); g_assert(e); - g_message("NEW ANNOUNCEMENT: %s.%i [%s]", i->hardware->name, i->protocol, t = flx_record_to_string(e->record)); - g_free(t); +/* g_message("NEW ANNOUNCEMENT: %s.%i [%s]", i->hardware->name, i->protocol, t = flx_record_to_string(e->record)); */ +/* g_free(t); */ - if (!flx_interface_match(i, e->interface, e->protocol) || !i->announcing) + if (!flx_interface_match(i, e->interface, e->protocol) || !i->announcing || e->flags & FLX_SERVER_ENTRY_NOANNOUNCE) + return; + + /* We don't want duplicate announcements */ + if (get_announcement(s, e, i)) return; - /* We don't want duplicates */ - for (a = e->announcements; a; a = a->by_entry_next) - if (a->interface == i) - return; - g_message("New announcement on interface %s.%i for entry [%s]", i->hardware->name, i->protocol, t = flx_record_to_string(e->record)); g_free(t); - - flx_interface_post_response(i, NULL, e->record, FALSE); - + a = g_new(flxAnnouncement, 1); a->server = s; a->interface = i; a->entry = e; - a->n_announced = 1; + + a->state = (e->flags & FLX_SERVER_ENTRY_UNIQUE) && !(e->flags & FLX_SERVER_ENTRY_NOPROBE) ? FLX_PROBING : FLX_ANNOUNCING; + a->n_iteration = 0; a->sec_delay = 1; + a->time_event = NULL; FLX_LLIST_PREPEND(flxAnnouncement, by_interface, i->announcements, a); FLX_LLIST_PREPEND(flxAnnouncement, by_entry, e->announcements, a); - - flx_elapse_time(&tv, a->sec_delay*1000, FLX_ANNOUNCEMENT_JITTER_MSEC); - a->time_event = flx_time_event_queue_add(s->time_event_queue, &tv, elapse_announce, a); + + send_packet(a); } void flx_announce_interface(flxServer *s, flxInterface *i) { @@ -89,7 +136,7 @@ void flx_announce_interface(flxServer *s, flxInterface *i) { if (!i->announcing) return; - g_message("ANNOUNCE INTERFACE"); +/* g_message("ANNOUNCE INTERFACE"); */ for (e = s->entries; e; e = e->entry_next) new_announcement(s, i, e); @@ -109,53 +156,102 @@ void flx_announce_entry(flxServer *s, flxServerEntry *e) { g_assert(s); g_assert(e); - g_message("ANNOUNCE ENTRY"); +/* g_message("ANNOUNCE ENTRY"); */ flx_interface_monitor_walk(s->monitor, e->interface, e->protocol, announce_walk_callback, e); } +gboolean flx_entry_established(flxServer *s, flxServerEntry *e, flxInterface *i) { + flxAnnouncement *a; + + g_assert(s); + g_assert(e); + g_assert(i); + + if (!(e->flags & FLX_SERVER_ENTRY_UNIQUE) || (e->flags & FLX_SERVER_ENTRY_NOPROBE)) + return TRUE; + + if ((a = get_announcement(s, e, i))) + if (a->state == FLX_PROBING) + return FALSE; + + return TRUE; +} + + static flxRecord *make_goodbye_record(flxRecord *r) { gchar *t; + flxRecord *g; g_assert(r); g_message("Preparing goodbye for record [%s]", t = flx_record_to_string(r)); g_free(t); - return flx_record_new(r->key, r->data, r->size, 0); + g = flx_record_copy(r); + g_assert(g->ref == 1); + g->ttl = 0; + + return g; +} + + +static void send_goodbye_callback(flxInterfaceMonitor *m, flxInterface *i, gpointer userdata) { + flxServerEntry *e = userdata; + flxRecord *g; + + g_assert(m); + g_assert(i); + g_assert(e); + + if (!flx_interface_match(i, e->interface, e->protocol)) + return; + + if (e->flags & FLX_SERVER_ENTRY_NOANNOUNCE) + return; + + if (!flx_entry_established(m->server, e, i)) + return; + + g = make_goodbye_record(e->record); + flx_interface_post_response(i, NULL, g, e->flags & FLX_SERVER_ENTRY_UNIQUE, TRUE); + flx_record_unref(g); } void flx_goodbye_interface(flxServer *s, flxInterface *i, gboolean goodbye) { g_assert(s); g_assert(i); - while (i->announcements) - remove_announcement(s, i->announcements); + g_message("goodbye interface: %s.%u", i->hardware->name, i->protocol); if (goodbye && flx_interface_relevant(i)) { flxServerEntry *e; for (e = s->entries; e; e = e->entry_next) - if (flx_interface_match(i, e->interface, e->protocol)) { - flxRecord *g = make_goodbye_record(e->record); - flx_interface_post_response(i, NULL, g, TRUE); - flx_record_unref(g); - } + send_goodbye_callback(s->monitor, i, e); } + + while (i->announcements) + remove_announcement(s, i->announcements); + + g_message("goodbye interface done: %s.%u", i->hardware->name, i->protocol); + } void flx_goodbye_entry(flxServer *s, flxServerEntry *e, gboolean goodbye) { g_assert(s); g_assert(e); + + g_message("goodbye entry: %p", e); + if (goodbye) + flx_interface_monitor_walk(s->monitor, 0, AF_UNSPEC, send_goodbye_callback, e); + while (e->announcements) remove_announcement(s, e->announcements); - - if (goodbye) { - flxRecord *g = make_goodbye_record(e->record); - flx_server_post_response(s, e->interface, e->protocol, g); - flx_record_unref(g); - } + + g_message("goodbye entry done: %p", e); + } void flx_goodbye_all(flxServer *s, gboolean goodbye) { @@ -163,6 +259,12 @@ void flx_goodbye_all(flxServer *s, gboolean goodbye) { g_assert(s); + g_message("goodbye all"); + for (e = s->entries; e; e = e->entry_next) flx_goodbye_entry(s, e, goodbye); + + g_message("goodbye all done"); + } +