aboutsummaryrefslogtreecommitdiff
path: root/src/dns
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-06-25 16:05:25 +0000
committerChristian Grothoff <christian@grothoff.org>2016-06-25 16:05:25 +0000
commitbdcff09ee219e8b301e63abecd758753c394ad5b (patch)
tree65ec86398a086e1b2c22aca8543cc68c4c3b3238 /src/dns
parent91ef3e6d0d4935dfa6dae561587b2e1d65fe07fd (diff)
downloadgnunet-bdcff09ee219e8b301e63abecd758753c394ad5b.tar.gz
gnunet-bdcff09ee219e8b301e63abecd758753c394ad5b.zip
convert dns api to MQ
Diffstat (limited to 'src/dns')
-rw-r--r--src/dns/dns_api.c347
1 files changed, 108 insertions, 239 deletions
diff --git a/src/dns/dns_api.c b/src/dns/dns_api.c
index f96ac3142..1d212e5d1 100644
--- a/src/dns/dns_api.c
+++ b/src/dns/dns_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2012 GNUnet e.V. 3 Copyright (C) 2012, 2016 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -29,29 +29,6 @@
29 29
30 30
31/** 31/**
32 * Reply to send to service.
33 */
34struct ReplyQueueEntry
35{
36 /**
37 * Kept in DLL.
38 */
39 struct ReplyQueueEntry *next;
40
41 /**
42 * Kept in DLL.
43 */
44 struct ReplyQueueEntry *prev;
45
46 /**
47 * Message to transmit, allocated at the end of this struct.
48 */
49 const struct GNUNET_MessageHeader *msg;
50
51};
52
53
54/**
55 * Handle to identify an individual DNS request. 32 * Handle to identify an individual DNS request.
56 */ 33 */
57struct GNUNET_DNS_RequestHandle 34struct GNUNET_DNS_RequestHandle
@@ -84,12 +61,7 @@ struct GNUNET_DNS_Handle
84 /** 61 /**
85 * Connection to DNS service, or NULL. 62 * Connection to DNS service, or NULL.
86 */ 63 */
87 struct GNUNET_CLIENT_Connection *dns_connection; 64 struct GNUNET_MQ_Handle *mq;
88
89 /**
90 * Handle to active transmission request, or NULL.
91 */
92 struct GNUNET_CLIENT_TransmitHandle *dns_transmit_handle;
93 65
94 /** 66 /**
95 * Configuration to use. 67 * Configuration to use.
@@ -102,24 +74,14 @@ struct GNUNET_DNS_Handle
102 GNUNET_DNS_RequestHandler rh; 74 GNUNET_DNS_RequestHandler rh;
103 75
104 /** 76 /**
105 * Closure for 'rh'. 77 * Closure for @e rh.
106 */ 78 */
107 void *rh_cls; 79 void *rh_cls;
108 80
109 /** 81 /**
110 * Head of replies to transmit.
111 */
112 struct ReplyQueueEntry *rq_head;
113
114 /**
115 * Tail of replies to transmit.
116 */
117 struct ReplyQueueEntry *rq_tail;
118
119 /**
120 * Task to reconnect to the service. 82 * Task to reconnect to the service.
121 */ 83 */
122 struct GNUNET_SCHEDULER_Task * reconnect_task; 84 struct GNUNET_SCHEDULER_Task *reconnect_task;
123 85
124 /** 86 /**
125 * Re-connect counter, to make sure we did not reconnect in the meantime. 87 * Re-connect counter, to make sure we did not reconnect in the meantime.
@@ -132,11 +94,6 @@ struct GNUNET_DNS_Handle
132 enum GNUNET_DNS_Flags flags; 94 enum GNUNET_DNS_Flags flags;
133 95
134 /** 96 /**
135 * Did we start the receive loop yet?
136 */
137 int in_receive;
138
139 /**
140 * Number of GNUNET_DNS_RequestHandles we have outstanding. Must be 0 before 97 * Number of GNUNET_DNS_RequestHandles we have outstanding. Must be 0 before
141 * we can be disconnected. 98 * we can be disconnected.
142 */ 99 */
@@ -145,73 +102,71 @@ struct GNUNET_DNS_Handle
145 102
146 103
147/** 104/**
148 * Add the given reply to our transmission queue and trigger sending if needed. 105 * Reconnect to the DNS service.
106 *
107 * @param cls handle with the connection to connect
108 * @param tc scheduler context (unused)
109 */
110static void
111reconnect (void *cls);
112
113
114/**
115 * Drop the existing connection and reconnect to the DNS service.
149 * 116 *
150 * @param dh handle with the connection 117 * @param dh handle with the connection
151 * @param qe reply to queue
152 */ 118 */
153static void 119static void
154queue_reply (struct GNUNET_DNS_Handle *dh, 120force_reconnect (struct GNUNET_DNS_Handle *dh)
155 struct ReplyQueueEntry *qe); 121{
122 if (NULL != dh->mq)
123 {
124 GNUNET_MQ_destroy (dh->mq);
125 dh->mq = NULL;
126 }
127 dh->reconnect_task =
128 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
129 &reconnect,
130 dh);
131}
156 132
157 133
158/** 134/**
159 * Reconnect to the DNS service. 135 * Generic error handler, called with the appropriate error code and
136 * the same closure specified at the creation of the message queue.
137 * Not every message queue implementation supports an error handler.
160 * 138 *
161 * @param cls handle with the connection to connect 139 * @param cls closure with the `struct GNUNET_DNS_Handle *`
162 * @param tc scheduler context (unused) 140 * @param error error code
163 */ 141 */
164static void 142static void
165reconnect (void *cls) 143mq_error_handler (void *cls,
144 enum GNUNET_MQ_Error error)
166{ 145{
167 struct GNUNET_DNS_Handle *dh = cls; 146 struct GNUNET_DNS_Handle *dh = cls;
168 struct ReplyQueueEntry *qe;
169 struct GNUNET_DNS_Register *msg;
170 147
171 dh->reconnect_task = NULL; 148 force_reconnect (dh);
172 dh->dns_connection = GNUNET_CLIENT_connect ("dns", dh->cfg);
173 if (NULL == dh->dns_connection)
174 return;
175 dh->generation++;
176 qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) +
177 sizeof (struct GNUNET_DNS_Register));
178 msg = (struct GNUNET_DNS_Register*) &qe[1];
179 qe->msg = &msg->header;
180 msg->header.size = htons (sizeof (struct GNUNET_DNS_Register));
181 msg->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT);
182 msg->flags = htonl (dh->flags);
183 queue_reply (dh, qe);
184} 149}
185 150
186 151
152
187/** 153/**
188 * Disconnect from the DNS service. 154 * This receives packets from the DNS service and calls the application to
155 * check that the request is well-formed
189 * 156 *
190 * @param dh handle with the connection to disconnect 157 * @param cls the struct GNUNET_DNS_Handle
158 * @param req message from the service (request)
191 */ 159 */
192static void 160static int
193disconnect (struct GNUNET_DNS_Handle *dh) 161check_request (void *cls,
162 const struct GNUNET_DNS_Request *req)
194{ 163{
195 struct ReplyQueueEntry *qe; 164 if (0 != ntohl (req->reserved))
196
197 if (NULL != dh->dns_transmit_handle)
198 {
199 GNUNET_CLIENT_notify_transmit_ready_cancel (dh->dns_transmit_handle);
200 dh->dns_transmit_handle = NULL;
201 }
202 if (NULL != dh->dns_connection)
203 { 165 {
204 GNUNET_CLIENT_disconnect (dh->dns_connection); 166 GNUNET_break (0);
205 dh->dns_connection = NULL; 167 return GNUNET_SYSERR;
206 }
207 while (NULL != (qe = dh->rq_head))
208 {
209 GNUNET_CONTAINER_DLL_remove (dh->rq_head,
210 dh->rq_tail,
211 qe);
212 GNUNET_free (qe);
213 } 168 }
214 dh->in_receive = GNUNET_NO; 169 return GNUNET_OK;
215} 170}
216 171
217 172
@@ -219,44 +174,17 @@ disconnect (struct GNUNET_DNS_Handle *dh)
219 * This receives packets from the DNS service and calls the application to 174 * This receives packets from the DNS service and calls the application to
220 * handle it. 175 * handle it.
221 * 176 *
222 * @param cls the struct GNUNET_DNS_Handle 177 * @param cls the `struct GNUNET_DNS_Handle *`
223 * @param msg message from the service (request) 178 * @param msg message from the service (request)
224 */ 179 */
225static void 180static void
226request_handler (void *cls, 181handle_request (void *cls,
227 const struct GNUNET_MessageHeader *msg) 182 const struct GNUNET_DNS_Request *req)
228{ 183{
229 struct GNUNET_DNS_Handle *dh = cls; 184 struct GNUNET_DNS_Handle *dh = cls;
230 const struct GNUNET_DNS_Request *req; 185 size_t payload_length = ntohs (req->header.size) - sizeof (*req);
231 struct GNUNET_DNS_RequestHandle *rh; 186 struct GNUNET_DNS_RequestHandle *rh;
232 size_t payload_length;
233 187
234 /* the service disconnected, reconnect after short wait */
235 if (msg == NULL)
236 {
237 disconnect (dh);
238 dh->reconnect_task =
239 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
240 &reconnect, dh);
241 return;
242 }
243 if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST) ||
244 (ntohs (msg->size) < sizeof (struct GNUNET_DNS_Request)) )
245 {
246 /* the service did something strange, reconnect immediately */
247 GNUNET_break (0);
248 disconnect (dh);
249 dh->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, dh);
250 return;
251 }
252 req = (const struct GNUNET_DNS_Request *) msg;
253 GNUNET_break (ntohl (req->reserved) == 0);
254 payload_length = ntohs (req->header.size) - sizeof (struct GNUNET_DNS_Request);
255 GNUNET_CLIENT_receive (dh->dns_connection,
256 &request_handler, dh,
257 GNUNET_TIME_UNIT_FOREVER_REL);
258
259 /* finally, pass request to callback for answers */
260 rh = GNUNET_new (struct GNUNET_DNS_RequestHandle); 188 rh = GNUNET_new (struct GNUNET_DNS_RequestHandle);
261 rh->dh =dh; 189 rh->dh =dh;
262 rh->request_id = req->request_id; 190 rh->request_id = req->request_id;
@@ -270,96 +198,38 @@ request_handler (void *cls,
270 198
271 199
272/** 200/**
273 * Callback called by notify_transmit_ready; sends DNS replies 201 * Reconnect to the DNS service.
274 * to the DNS service.
275 * 202 *
276 * @param cls the struct GNUNET_DNS_Handle 203 * @param cls handle with the connection to connect
277 * @param size number of bytes available in buf
278 * @param buf where to copy the message for transmission
279 * @return number of bytes copied to buf
280 */ 204 */
281static size_t 205static void
282send_response (void *cls, size_t size, void *buf) 206reconnect (void *cls)
283{ 207{
208 GNUNET_MQ_hd_var_size (request,
209 GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST,
210 struct GNUNET_DNS_Request);
284 struct GNUNET_DNS_Handle *dh = cls; 211 struct GNUNET_DNS_Handle *dh = cls;
285 struct ReplyQueueEntry *qe; 212 struct GNUNET_MQ_MessageHandler handlers[] = {
286 size_t len; 213 make_request_handler (dh),
287 214 GNUNET_MQ_handler_end ()
288 dh->dns_transmit_handle = NULL; 215 };
289 if (NULL == buf) 216 struct GNUNET_MQ_Envelope *env;
290 { 217 struct GNUNET_DNS_Register *msg;
291 disconnect (dh);
292 dh->reconnect_task =
293 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
294 &reconnect, dh);
295 return 0;
296 }
297 qe = dh->rq_head;
298 if (NULL == qe)
299 return 0;
300 len = ntohs (qe->msg->size);
301 if (len > size)
302 {
303 dh->dns_transmit_handle =
304 GNUNET_CLIENT_notify_transmit_ready (dh->dns_connection,
305 len,
306 GNUNET_TIME_UNIT_FOREVER_REL,
307 GNUNET_NO,
308 &send_response, dh);
309 return 0;
310 }
311 memcpy (buf, qe->msg, len);
312 GNUNET_CONTAINER_DLL_remove (dh->rq_head,
313 dh->rq_tail,
314 qe);
315 GNUNET_free (qe);
316 if (GNUNET_NO == dh->in_receive)
317 {
318 dh->in_receive = GNUNET_YES;
319 GNUNET_CLIENT_receive (dh->dns_connection,
320 &request_handler, dh,
321 GNUNET_TIME_UNIT_FOREVER_REL);
322 }
323 if (NULL != (qe = dh->rq_head))
324 {
325 dh->dns_transmit_handle =
326 GNUNET_CLIENT_notify_transmit_ready (dh->dns_connection,
327 ntohs (qe->msg->size),
328 GNUNET_TIME_UNIT_FOREVER_REL,
329 GNUNET_NO,
330 &send_response, dh);
331 }
332 return len;
333}
334
335 218
336/** 219 dh->reconnect_task = NULL;
337 * Add the given reply to our transmission queue and trigger sending if needed. 220 dh->mq = GNUNET_CLIENT_connecT (dh->cfg,
338 * 221 "dns",
339 * @param dh handle with the connection 222 handlers,
340 * @param qe reply to queue 223 &mq_error_handler,
341 */ 224 dh);
342static void 225 if (NULL == dh->mq)
343queue_reply (struct GNUNET_DNS_Handle *dh,
344 struct ReplyQueueEntry *qe)
345{
346 if (NULL == dh->dns_connection)
347 {
348 GNUNET_free (qe);
349 return;
350 }
351 GNUNET_CONTAINER_DLL_insert_tail (dh->rq_head,
352 dh->rq_tail,
353 qe);
354 if (NULL != dh->dns_transmit_handle)
355 return; 226 return;
356 /* trigger sending */ 227 dh->generation++;
357 dh->dns_transmit_handle = 228 env = GNUNET_MQ_msg (msg,
358 GNUNET_CLIENT_notify_transmit_ready (dh->dns_connection, 229 GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT);
359 ntohs (dh->rq_head->msg->size), 230 msg->flags = htonl (dh->flags);
360 GNUNET_TIME_UNIT_FOREVER_REL, 231 GNUNET_MQ_send (dh->mq,
361 GNUNET_NO, 232 env);
362 &send_response, dh);
363} 233}
364 234
365 235
@@ -376,7 +246,7 @@ queue_reply (struct GNUNET_DNS_Handle *dh,
376void 246void
377GNUNET_DNS_request_forward (struct GNUNET_DNS_RequestHandle *rh) 247GNUNET_DNS_request_forward (struct GNUNET_DNS_RequestHandle *rh)
378{ 248{
379 struct ReplyQueueEntry *qe; 249 struct GNUNET_MQ_Envelope *env;
380 struct GNUNET_DNS_Response *resp; 250 struct GNUNET_DNS_Response *resp;
381 251
382 GNUNET_assert (0 < rh->dh->pending_requests--); 252 GNUNET_assert (0 < rh->dh->pending_requests--);
@@ -385,15 +255,12 @@ GNUNET_DNS_request_forward (struct GNUNET_DNS_RequestHandle *rh)
385 GNUNET_free (rh); 255 GNUNET_free (rh);
386 return; 256 return;
387 } 257 }
388 qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) + 258 env = GNUNET_MQ_msg (resp,
389 sizeof (struct GNUNET_DNS_Response)); 259 GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
390 resp = (struct GNUNET_DNS_Response*) &qe[1];
391 qe->msg = &resp->header;
392 resp->header.size = htons (sizeof (struct GNUNET_DNS_Response));
393 resp->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
394 resp->drop_flag = htonl (1); 260 resp->drop_flag = htonl (1);
395 resp->request_id = rh->request_id; 261 resp->request_id = rh->request_id;
396 queue_reply (rh->dh, qe); 262 GNUNET_MQ_send (rh->dh->mq,
263 env);
397 GNUNET_free (rh); 264 GNUNET_free (rh);
398} 265}
399 266
@@ -407,7 +274,7 @@ GNUNET_DNS_request_forward (struct GNUNET_DNS_RequestHandle *rh)
407void 274void
408GNUNET_DNS_request_drop (struct GNUNET_DNS_RequestHandle *rh) 275GNUNET_DNS_request_drop (struct GNUNET_DNS_RequestHandle *rh)
409{ 276{
410 struct ReplyQueueEntry *qe; 277 struct GNUNET_MQ_Envelope *env;
411 struct GNUNET_DNS_Response *resp; 278 struct GNUNET_DNS_Response *resp;
412 279
413 GNUNET_assert (0 < rh->dh->pending_requests--); 280 GNUNET_assert (0 < rh->dh->pending_requests--);
@@ -416,15 +283,12 @@ GNUNET_DNS_request_drop (struct GNUNET_DNS_RequestHandle *rh)
416 GNUNET_free (rh); 283 GNUNET_free (rh);
417 return; 284 return;
418 } 285 }
419 qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) + 286 env = GNUNET_MQ_msg (resp,
420 sizeof (struct GNUNET_DNS_Response)); 287 GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
421 resp = (struct GNUNET_DNS_Response*) &qe[1];
422 qe->msg = &resp->header;
423 resp->header.size = htons (sizeof (struct GNUNET_DNS_Response));
424 resp->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
425 resp->request_id = rh->request_id; 288 resp->request_id = rh->request_id;
426 resp->drop_flag = htonl (0); 289 resp->drop_flag = htonl (0);
427 queue_reply (rh->dh, qe); 290 GNUNET_MQ_send (rh->dh->mq,
291 env);
428 GNUNET_free (rh); 292 GNUNET_free (rh);
429} 293}
430 294
@@ -435,7 +299,7 @@ GNUNET_DNS_request_drop (struct GNUNET_DNS_RequestHandle *rh)
435 * the modifications the function might have made). 299 * the modifications the function might have made).
436 * 300 *
437 * @param rh request that should now be answered 301 * @param rh request that should now be answered
438 * @param reply_length size of reply (uint16_t to force sane size) 302 * @param reply_length size of @a reply (uint16_t to force sane size)
439 * @param reply reply data 303 * @param reply reply data
440 */ 304 */
441void 305void
@@ -443,7 +307,7 @@ GNUNET_DNS_request_answer (struct GNUNET_DNS_RequestHandle *rh,
443 uint16_t reply_length, 307 uint16_t reply_length,
444 const char *reply) 308 const char *reply)
445{ 309{
446 struct ReplyQueueEntry *qe; 310 struct GNUNET_MQ_Envelope *env;
447 struct GNUNET_DNS_Response *resp; 311 struct GNUNET_DNS_Response *resp;
448 312
449 GNUNET_assert (0 < rh->dh->pending_requests--); 313 GNUNET_assert (0 < rh->dh->pending_requests--);
@@ -452,22 +316,23 @@ GNUNET_DNS_request_answer (struct GNUNET_DNS_RequestHandle *rh,
452 GNUNET_free (rh); 316 GNUNET_free (rh);
453 return; 317 return;
454 } 318 }
455 if (reply_length + sizeof (struct GNUNET_DNS_Response) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 319 if (reply_length + sizeof (struct GNUNET_DNS_Response)
320 >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
456 { 321 {
457 GNUNET_break (0); 322 GNUNET_break (0);
458 GNUNET_free (rh); 323 GNUNET_free (rh);
459 return; 324 return;
460 } 325 }
461 qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) + 326 env = GNUNET_MQ_msg_extra (resp,
462 sizeof (struct GNUNET_DNS_Response) + reply_length); 327 reply_length,
463 resp = (struct GNUNET_DNS_Response*) &qe[1]; 328 GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
464 qe->msg = &resp->header;
465 resp->header.size = htons (sizeof (struct GNUNET_DNS_Response) + reply_length);
466 resp->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
467 resp->drop_flag = htonl (2); 329 resp->drop_flag = htonl (2);
468 resp->request_id = rh->request_id; 330 resp->request_id = rh->request_id;
469 memcpy (&resp[1], reply, reply_length); 331 memcpy (&resp[1],
470 queue_reply (rh->dh, qe); 332 reply,
333 reply_length);
334 GNUNET_MQ_send (rh->dh->mq,
335 env);
471 GNUNET_free (rh); 336 GNUNET_free (rh);
472} 337}
473 338
@@ -476,9 +341,9 @@ GNUNET_DNS_request_answer (struct GNUNET_DNS_RequestHandle *rh,
476 * Connect to the service-dns 341 * Connect to the service-dns
477 * 342 *
478 * @param cfg configuration to use 343 * @param cfg configuration to use
479 * @param flags when to call rh 344 * @param flags when to call @a rh
480 * @param rh function to call with DNS requests 345 * @param rh function to call with DNS requests
481 * @param rh_cls closure to pass to rh 346 * @param rh_cls closure to pass to @a rh
482 * @return DNS handle 347 * @return DNS handle
483 */ 348 */
484struct GNUNET_DNS_Handle * 349struct GNUNET_DNS_Handle *
@@ -507,15 +372,19 @@ GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
507void 372void
508GNUNET_DNS_disconnect (struct GNUNET_DNS_Handle *dh) 373GNUNET_DNS_disconnect (struct GNUNET_DNS_Handle *dh)
509{ 374{
375 if (NULL != dh->mq)
376 {
377 GNUNET_MQ_destroy (dh->mq);
378 dh->mq = NULL;
379 }
510 if (NULL != dh->reconnect_task) 380 if (NULL != dh->reconnect_task)
511 { 381 {
512 GNUNET_SCHEDULER_cancel (dh->reconnect_task); 382 GNUNET_SCHEDULER_cancel (dh->reconnect_task);
513 dh->reconnect_task = NULL; 383 dh->reconnect_task = NULL;
514 } 384 }
515 disconnect (dh);
516 /* make sure client has no pending requests left over! */ 385 /* make sure client has no pending requests left over! */
517 GNUNET_assert (0 == dh->pending_requests); 386 GNUNET_break (0 == dh->pending_requests);
518 GNUNET_free (dh); 387 GNUNET_free (dh);
519} 388}
520 389
521/* end of dns_api_new.c */ 390/* end of dns_api.c */