4 flxPacketScheduler *flx_packet_scheduler_new(flxServer *server, flxInterface *i) {
10 s = g_new(flxPacketScheduler, 1);
14 FLX_LLIST_HEAD_INIT(flxQueryJob, s->query_jobs);
15 FLX_LLIST_HEAD_INIT(flxResponseJob, s->response_jobs);
20 static void query_job_free(flxPacketScheduler *s, flxQueryJob *qj) {
24 flx_time_event_queue_remove(qj->scheduler->server->time_event_queue, qj->time_event);
26 FLX_LLIST_REMOVE(flxQueryJob, jobs, s->query_jobs, qj);
28 flx_key_unref(qj->key);
32 static void response_job_free(flxPacketScheduler *s, flxResponseJob *rj) {
36 flx_time_event_queue_remove(rj->scheduler->server->time_event_queue, rj->time_event);
38 FLX_LLIST_REMOVE(flxResponseJob, jobs, s->response_jobs, rj);
40 flx_record_unref(rj->record);
44 void flx_packet_scheduler_free(flxPacketScheduler *s) {
51 while ((qj = s->query_jobs))
52 query_job_free(s, qj);
53 while ((rj = s->response_jobs))
54 response_job_free(s, rj);
59 static guint8* packet_add_query_job(flxPacketScheduler *s, flxDnsPacket *p, flxQueryJob *qj) {
66 if ((d = flx_dns_packet_append_key(p, qj->key))) {
71 /* Drop query after 100ms from history */
72 flx_elapse_time(&tv, 100, 0);
73 flx_time_event_queue_update(s->server->time_event_queue, qj->time_event, &tv);
79 static void query_elapse(flxTimeEvent *e, gpointer data) {
80 flxQueryJob *qj = data;
81 flxPacketScheduler *s;
90 /* Lets remove it from the history */
91 query_job_free(s, qj);
95 p = flx_dns_packet_new_query(s->interface->hardware->mtu - 48);
96 d = packet_add_query_job(s, p, qj);
100 /* Try to fill up packet with more queries, if available */
101 for (qj = s->query_jobs; qj; qj = qj->jobs_next) {
106 if (!packet_add_query_job(s, p, qj))
112 flx_dns_packet_set_field(p, DNS_FIELD_QDCOUNT, n);
113 flx_interface_send_packet(s->interface, p);
114 flx_dns_packet_free(p);
117 static flxQueryJob* look_for_query(flxPacketScheduler *s, flxKey *key) {
123 for (qj = s->query_jobs; qj; qj = qj->jobs_next)
124 if (flx_key_equal(qj->key, key))
130 void flx_packet_scheduler_post_query(flxPacketScheduler *s, flxKey *key) {
137 if (look_for_query(s, key))
140 qj = g_new(flxQueryJob, 1);
141 qj->key = flx_key_ref(key);
144 flx_elapse_time(&tv, 100, 0);
145 qj->time_event = flx_time_event_queue_add(s->server->time_event_queue, &tv, query_elapse, qj);
148 FLX_LLIST_PREPEND(flxQueryJob, jobs, s->query_jobs, qj);
151 static guint8* packet_add_response_job(flxPacketScheduler *s, flxDnsPacket *p, flxResponseJob *rj) {
158 if ((d = flx_dns_packet_append_record(p, rj->record, FALSE))) {
163 /* Drop response after 1s from history */
164 flx_elapse_time(&tv, 1000, 0);
165 flx_time_event_queue_update(s->server->time_event_queue, rj->time_event, &tv);
172 static void response_elapse(flxTimeEvent *e, gpointer data) {
173 flxResponseJob *rj = data;
174 flxPacketScheduler *s;
183 /* Lets remove it from the history */
184 response_job_free(s, rj);
188 p = flx_dns_packet_new_response(s->interface->hardware->mtu - 200);
189 d = packet_add_response_job(s, p, rj);
193 /* Try to fill up packet with more responses, if available */
194 for (rj = s->response_jobs; rj; rj = rj->jobs_next) {
199 if (!packet_add_response_job(s, p, rj))
205 flx_dns_packet_set_field(p, DNS_FIELD_ANCOUNT, n);
206 flx_interface_send_packet(s->interface, p);
207 flx_dns_packet_free(p);
210 static flxResponseJob* look_for_response(flxPacketScheduler *s, flxRecord *record) {
216 for (rj = s->response_jobs; rj; rj = rj->jobs_next)
217 if (flx_record_equal(rj->record, record))
223 void flx_packet_scheduler_post_response(flxPacketScheduler *s, flxRecord *record) {
230 if (look_for_response(s, record))
233 rj = g_new(flxResponseJob, 1);
234 rj->record = flx_record_ref(record);
237 flx_elapse_time(&tv, 20, 100);
238 rj->time_event = flx_time_event_queue_add(s->server->time_event_queue, &tv, response_elapse, rj);
241 FLX_LLIST_PREPEND(flxResponseJob, jobs, s->response_jobs, rj);
244 void flx_packet_scheduler_drop_query(flxPacketScheduler *s, flxKey *key) {
250 for (qj = s->query_jobs; qj; qj = qj->jobs_next)
251 if (flx_key_equal(qj->key, key)) {
257 /* Drop query after 100ms from history */
258 flx_elapse_time(&tv, 100, 0);
259 flx_time_event_queue_update(s->server->time_event_queue, qj->time_event, &tv);
266 void flx_packet_scheduler_drop_response(flxPacketScheduler *s, flxRecord *record) {
272 for (rj = s->response_jobs; rj; rj = rj->jobs_next)
273 if (flx_record_equal(rj->record, record)) {
279 /* Drop response after 100ms from history */
280 flx_elapse_time(&tv, 100, 0);
281 flx_time_event_queue_update(s->server->time_event_queue, rj->time_event, &tv);