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