4 flxPacketScheduler *flx_packet_scheduler_new(flxServer *server, flxInterface *i, guchar protocol) {
10 s = g_new(flxPacketScheduler, 1);
13 s->protocol = protocol;
15 FLX_LLIST_HEAD_INIT(flxQueryJob, s->query_jobs);
16 FLX_LLIST_HEAD_INIT(flxResponseJob, s->response_jobs);
21 static void query_job_free(flxPacketScheduler *s, flxQueryJob *qj) {
25 flx_time_event_queue_remove(qj->scheduler->server->time_event_queue, qj->time_event);
27 FLX_LLIST_REMOVE(flxQueryJob, jobs, s->query_jobs, qj);
29 flx_key_unref(qj->key);
33 static void response_job_free(flxPacketScheduler *s, flxResponseJob *rj) {
37 flx_time_event_queue_remove(rj->scheduler->server->time_event_queue, rj->time_event);
39 FLX_LLIST_REMOVE(flxResponseJob, jobs, s->response_jobs, rj);
41 flx_record_unref(rj->record);
45 void flx_packet_scheduler_free(flxPacketScheduler *s) {
52 while ((qj = s->query_jobs))
53 query_job_free(s, qj);
54 while ((rj = s->response_jobs))
55 response_job_free(s, rj);
60 static guint8* packet_add_query_job(flxPacketScheduler *s, flxDnsPacket *p, flxQueryJob *qj) {
67 if ((d = flx_dns_packet_append_key(p, qj->key))) {
72 /* Drop query after 100ms from history */
73 flx_elapse_time(&tv, 100, 0);
74 flx_time_event_queue_update(s->server->time_event_queue, qj->time_event, &tv);
80 static void query_elapse(flxTimeEvent *e, gpointer data) {
81 flxQueryJob *qj = data;
82 flxPacketScheduler *s;
91 /* Lets remove it from the history */
92 query_job_free(s, qj);
96 p = flx_dns_packet_new_query(s->interface->mtu - 200);
97 d = packet_add_query_job(s, p, qj);
101 /* Try to fill up packet with more queries, if available */
102 for (qj = s->query_jobs; qj; qj = qj->jobs_next) {
107 if (!packet_add_query_job(s, p, qj))
113 flx_dns_packet_set_field(p, DNS_FIELD_QDCOUNT, n);
114 flx_interface_send_packet(s->interface, s->protocol, p);
115 flx_dns_packet_free(p);
118 static flxQueryJob* look_for_query(flxPacketScheduler *s, flxKey *key) {
124 for (qj = s->query_jobs; qj; qj = qj->jobs_next)
125 if (flx_key_equal(qj->key, key))
131 void flx_packet_scheduler_post_query(flxPacketScheduler *s, flxKey *key) {
138 if (look_for_query(s, key))
141 qj = g_new(flxQueryJob, 1);
142 qj->key = flx_key_ref(key);
145 flx_elapse_time(&tv, 100, 0);
146 qj->time_event = flx_time_event_queue_add(s->server->time_event_queue, &tv, query_elapse, qj);
149 FLX_LLIST_PREPEND(flxQueryJob, jobs, s->query_jobs, qj);
152 static guint8* packet_add_response_job(flxPacketScheduler *s, flxDnsPacket *p, flxResponseJob *rj) {
159 if ((d = flx_dns_packet_append_record(p, rj->record, FALSE))) {
164 /* Drop response after 1s from history */
165 flx_elapse_time(&tv, 1000, 0);
166 flx_time_event_queue_update(s->server->time_event_queue, rj->time_event, &tv);
173 static void response_elapse(flxTimeEvent *e, gpointer data) {
174 flxResponseJob *rj = data;
175 flxPacketScheduler *s;
184 /* Lets remove it from the history */
185 response_job_free(s, rj);
189 p = flx_dns_packet_new_response(s->interface->mtu - 200);
190 d = packet_add_response_job(s, p, rj);
194 /* Try to fill up packet with more responses, if available */
195 for (rj = s->response_jobs; rj; rj = rj->jobs_next) {
200 if (!packet_add_response_job(s, p, rj))
206 flx_dns_packet_set_field(p, DNS_FIELD_ANCOUNT, n);
207 flx_interface_send_packet(s->interface, s->protocol, p);
208 flx_dns_packet_free(p);
211 static flxResponseJob* look_for_response(flxPacketScheduler *s, flxRecord *record) {
217 for (rj = s->response_jobs; rj; rj = rj->jobs_next)
218 if (flx_record_equal(rj->record, record))
224 void flx_packet_scheduler_post_response(flxPacketScheduler *s, flxRecord *record) {
231 if (look_for_response(s, record))
234 rj = g_new(flxResponseJob, 1);
235 rj->record = flx_record_ref(record);
238 flx_elapse_time(&tv, 20, 100);
239 rj->time_event = flx_time_event_queue_add(s->server->time_event_queue, &tv, response_elapse, rj);
242 FLX_LLIST_PREPEND(flxResponseJob, jobs, s->response_jobs, rj);
245 void flx_packet_scheduler_drop_query(flxPacketScheduler *s, flxKey *key) {
251 for (qj = s->query_jobs; qj; qj = qj->jobs_next)
252 if (flx_key_equal(qj->key, key)) {
258 /* Drop query after 100ms from history */
259 flx_elapse_time(&tv, 100, 0);
260 flx_time_event_queue_update(s->server->time_event_queue, qj->time_event, &tv);
267 void flx_packet_scheduler_drop_response(flxPacketScheduler *s, flxRecord *record) {
273 for (rj = s->response_jobs; rj; rj = rj->jobs_next)
274 if (flx_record_equal(rj->record, record)) {
280 /* Drop response after 100ms from history */
281 flx_elapse_time(&tv, 100, 0);
282 flx_time_event_queue_update(s->server->time_event_queue, rj->time_event, &tv);