]> git.meshlink.io Git - catta/blob - announce.c
* add subscription feature - with reissuing
[catta] / announce.c
1 #include "announce.h"
2 #include "util.h"
3
4 static void remove_announcement(flxServer *s, flxAnnouncement *a) {
5     g_assert(s);
6     g_assert(a);
7
8     flx_time_event_queue_remove(s->time_event_queue, a->time_event);
9
10     FLX_LLIST_REMOVE(flxAnnouncement, by_interface, a->interface->announcements, a);
11     FLX_LLIST_REMOVE(flxAnnouncement, by_entry, a->entry->announcements, a);
12     
13     g_free(a);
14 }
15
16 static void elapse_announce(flxTimeEvent *e, void *userdata) {
17     flxAnnouncement *a = userdata;
18     GTimeVal tv;
19     gchar *t;
20         
21     g_assert(e);
22     g_assert(a);
23
24     if (a->n_announced >= 3) {
25         g_message("Enough announcements for record [%s]", t = flx_record_to_string(a->entry->record));
26         g_free(t);
27         remove_announcement(a->server, a);
28         return;
29     }
30
31     flx_interface_post_response(a->interface, a->entry->record);
32     a->n_announced++;
33
34     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));
35     g_free(t);
36     
37     flx_elapse_time(&tv, 1000, 100);
38     flx_time_event_queue_update(a->server->time_event_queue, a->time_event, &tv);
39 }
40
41 static void new_announcement(flxServer *s, flxInterface *i, flxServerEntry *e) {
42     flxAnnouncement *a;
43     GTimeVal tv;
44     gchar *t;
45
46     g_assert(s);
47     g_assert(i);
48     g_assert(e);
49
50     if (!flx_interface_match(i, e->interface, e->protocol) || !flx_interface_relevant(i))
51         return;
52
53     /* We don't want duplicates */
54     for (a = e->announcements; a; a = a->by_entry_next)
55         if (a->interface == i)
56             return;
57     
58     g_message("New announcement on interface %s.%i for entry [%s]", i->hardware->name, i->protocol, t = flx_record_to_string(e->record));
59     g_free(t);
60     
61     flx_interface_post_response(i, e->record);
62     
63     a = g_new(flxAnnouncement, 1);
64     a->server = s;
65     a->interface = i;
66     a->entry = e;
67     a->n_announced = 1;
68     
69     FLX_LLIST_PREPEND(flxAnnouncement, by_interface, i->announcements, a);
70     FLX_LLIST_PREPEND(flxAnnouncement, by_entry, e->announcements, a);
71     
72     flx_elapse_time(&tv, 1000, 100);
73     a->time_event = flx_time_event_queue_add(s->time_event_queue, &tv, elapse_announce, a);
74 }
75
76 void flx_announce_interface(flxServer *s, flxInterface *i) {
77     flxServerEntry *e;
78     
79     g_assert(s);
80     g_assert(i);
81
82     if (!flx_interface_relevant(i))
83         return;
84     
85     for (e = s->entries; e; e = e->entry_next)
86         new_announcement(s, i, e);
87 }
88
89 void flx_announce_entry(flxServer *s, flxServerEntry *e) {
90     g_assert(s);
91     g_assert(e);
92
93     if (e->interface > 0) {
94
95         if (e->protocol != AF_UNSPEC) {
96             flxInterface *i;
97     
98             if ((i = flx_interface_monitor_get_interface(s->monitor, e->interface, e->protocol)))
99                 new_announcement(s, i, e);
100         } else {
101             flxHwInterface *hw;
102
103             if ((hw = flx_interface_monitor_get_hw_interface(s->monitor, e->interface))) {
104                 flxInterface *i;
105
106                 for (i = hw->interfaces; i; i = i->by_hardware_next)
107                     new_announcement(s, i, e);
108             }
109         }
110     } else {
111         flxInterface *i;
112
113         for (i = s->monitor->interfaces; i; i = i->interface_next)
114             new_announcement(s, i, e);
115     }
116 }
117
118 static flxRecord *make_goodbye_record(flxRecord *r) {
119     gchar *t;
120     
121     g_assert(r);
122
123     g_message("Preparing goodbye for record [%s]", t = flx_record_to_string(r));
124     g_free(t);
125
126     return flx_record_new(r->key, r->data, r->size, 0);
127 }
128     
129 void flx_goodbye_interface(flxServer *s, flxInterface *i, gboolean goodbye) {
130     g_assert(s);
131     g_assert(i);
132
133     while (i->announcements)
134         remove_announcement(s, i->announcements);
135
136     if (goodbye && flx_interface_relevant(i)) {
137         flxServerEntry *e;
138         
139         for (e = s->entries; e; e = e->entry_next)
140             if (flx_interface_match(i, e->interface, e->protocol)) {
141                 flxRecord *g = make_goodbye_record(e->record);
142                 flx_interface_post_response(i, g);
143                 flx_record_unref(g);
144             }
145     }
146 }
147
148 void flx_goodbye_entry(flxServer *s, flxServerEntry *e, gboolean goodbye) {
149     g_assert(s);
150     g_assert(e);
151     
152     while (e->announcements)
153         remove_announcement(s, e->announcements);
154     
155     if (goodbye) {
156         flxRecord *g = make_goodbye_record(e->record);
157         flx_server_post_response(s, e->interface, e->protocol, g);
158         flx_record_unref(g);
159     }
160 }
161
162 void flx_goodbye_all(flxServer *s, gboolean goodbye) {
163     flxServerEntry *e;
164     
165     g_assert(s);
166
167     for (e = s->entries; e; e = e->entry_next)
168         flx_goodbye_entry(s, e, goodbye);
169 }