aboutsummaryrefslogtreecommitdiff
path: root/src/gns/gns_api.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2012-03-08 14:14:01 +0000
committerMartin Schanzenbach <mschanzenbach@posteo.de>2012-03-08 14:14:01 +0000
commit3a60024e089a38aa32fcafece7c257672abf4608 (patch)
treea3c36e0a87766bd85e450bd1b9c8766965a34710 /src/gns/gns_api.c
parent588b14ec0ec5c59d0dad37dcc0841c1ff0b2942c (diff)
downloadgnunet-3a60024e089a38aa32fcafece7c257672abf4608.tar.gz
gnunet-3a60024e089a38aa32fcafece7c257672abf4608.zip
-GNS service api change, replaced complicated buggy code
Diffstat (limited to 'src/gns/gns_api.c')
-rw-r--r--src/gns/gns_api.c680
1 files changed, 229 insertions, 451 deletions
diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c
index eaae4955f..47efe5058 100644
--- a/src/gns/gns_api.c
+++ b/src/gns/gns_api.c
@@ -46,130 +46,54 @@
46#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT 26 46#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT 26
47 47
48/** 48/**
49 * Entry in our list of messages to be (re-)transmitted. 49 * A QueueEntry.
50 */ 50 */
51struct PendingMessage 51struct GNUNET_GNS_QueueEntry
52{ 52{
53 /** 53 /**
54 * This is a doubly-linked list. 54 * DLL
55 */
56 struct PendingMessage *prev;
57
58 /**
59 * This is a doubly-linked list.
60 */
61 struct PendingMessage *next;
62
63 /**
64 * Message that is pending, allocated at the end
65 * of this struct.
66 */
67 const struct GNUNET_MessageHeader *msg;
68
69 /**
70 * Handle to the GNS API context.
71 */ 55 */
72 struct GNUNET_GNS_Handle *handle; 56 struct GNUNET_GNS_QueueEntry *next;
73 57
74 /**
75 * Continuation to call when the request has been
76 * transmitted (for the first time) to the service; can be NULL.
77 */
78 GNUNET_SCHEDULER_Task cont;
79
80 /**
81 * Closure for 'cont'.
82 */
83 void *cont_cls;
84
85 /**
86 * Unique ID for this request
87 */
88 uint64_t unique_id;
89
90 /**
91 * Free the saved message once sent, set to GNUNET_YES for messages
92 * that do not receive responses; GNUNET_NO if this pending message
93 * is aliased from a 'struct GNUNET_DHT_RouteHandle' and will be freed
94 * from there.
95 */
96
97 int free_on_send;
98 /**
99 * GNUNET_YES if this message is in our pending queue right now.
100 */
101 int in_pending_queue;
102
103};
104
105/**
106 * Handle to a Lookup request
107 */
108struct GNUNET_GNS_LookupHandle
109{
110
111 /**
112 * Iterator to call on data receipt
113 */
114 GNUNET_GNS_LookupIterator iter;
115
116 /** 58 /**
117 * Closure for the iterator callback 59 * DLL
118 */ 60 */
119 void *iter_cls; 61 struct GNUNET_GNS_QueueEntry *prev;
120 62
121 /** 63 /* request id */
122 * Main handle to this GNS api 64 uint32_t r_id;
123 */ 65
66 /* handle to gns */
124 struct GNUNET_GNS_Handle *gns_handle; 67 struct GNUNET_GNS_Handle *gns_handle;
125 68
126 /** 69 /* processor to call on shorten result */
127 * Key that this get request is for 70 GNUNET_GNS_ShortenResultProcessor proc;
128 */ 71
129 GNUNET_HashCode key; 72 /* processor closure */
130 73 void *proc_cls;
131 /** 74
132 * Unique identifier for this request (for key collisions).
133 */
134 uint64_t unique_id;
135
136 struct PendingMessage *message;
137
138}; 75};
139 76
140 77
141/** 78/**
142 * Handle to a shorten request 79 * Entry in our list of messages to be (re-)transmitted.
143 */ 80 */
144struct GNUNET_GNS_ShortenHandle 81struct PendingMessage
145{ 82{
146
147 /**
148 * Processor to call on data receipt
149 */
150 GNUNET_GNS_ShortenResultProcessor proc;
151
152 /** 83 /**
153 * Closure for the processor 84 * This is a doubly-linked list.
154 */
155 void *proc_cls;
156
157 /**
158 * Main handle to this GNS api
159 */ 85 */
160 struct GNUNET_GNS_Handle *gns_handle; 86 struct PendingMessage *prev;
161 87
162 /** 88 /**
163 * Key that this get request is for 89 * This is a doubly-linked list.
164 */ 90 */
165 GNUNET_HashCode key; 91 struct PendingMessage *next;
166 92
167 /** 93 /**
168 * Unique identifier for this request (for key collisions). 94 * Size of the message.
169 */ 95 */
170 uint64_t unique_id; 96 size_t size;
171
172 struct PendingMessage *message;
173 97
174}; 98};
175 99
@@ -194,40 +118,53 @@ struct GNUNET_GNS_Handle
194 * Currently pending transmission request (or NULL). 118 * Currently pending transmission request (or NULL).
195 */ 119 */
196 struct GNUNET_CLIENT_TransmitHandle *th; 120 struct GNUNET_CLIENT_TransmitHandle *th;
197 121
122 uint32_t r_id;
123
198 /** 124 /**
199 * Head of linked list of messages we would like to transmit. 125 * Head of linked list of shorten messages we would like to transmit.
200 */ 126 */
201 struct PendingMessage *pending_head; 127 struct PendingMessage *pending_head;
202 128
203 /** 129 /**
204 * Tail of linked list of messages we would like to transmit. 130 * Tail of linked list of shorten messages we would like to transmit.
205 */ 131 */
206 struct PendingMessage *pending_tail; 132 struct PendingMessage *pending_tail;
207 133
208 /** 134 /**
209 * Hash maps containing the current outstanding unique requests. 135 * Head of linked list of shorten messages we would like to transmit.
210 */ 136 */
211 struct GNUNET_CONTAINER_MultiHashMap *active_lookup_requests; 137 struct GNUNET_GNS_QueueEntry *shorten_head;
212 struct GNUNET_CONTAINER_MultiHashMap *active_shorten_requests;
213
214 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
215 138
216 /** 139 /**
217 * How quickly should we retry? Used for exponential back-off on 140 * Tail of linked list of shorten messages we would like to transmit.
218 * connect-errors. 141 */
142 struct GNUNET_GNS_QueueEntry *shorten_tail;
143
144 /**
145 * Head of linked list of lookup messages we would like to transmit.
219 */ 146 */
220 struct GNUNET_TIME_Relative retry_time; 147 struct GNUNET_GNS_QueueEntry *lookup_head;
221 148
222 /** 149 /**
223 * Generator for unique ids. 150 * Tail of linked list of lookup messages we would like to transmit.
224 */ 151 */
225 uint64_t uid_gen; 152 struct GNUNET_GNS_QueueEntry *lookup_tail;
153
154 /**
155 * Reconnect task
156 */
157 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
226 158
227 /** 159 /**
228 * Did we start our receive loop yet? 160 * Did we start our receive loop yet?
229 */ 161 */
230 int in_receive; 162 int in_receive;
163
164 /**
165 * Reconnect necessary
166 */
167 int reconnect;
231}; 168};
232 169
233/** 170/**
@@ -237,140 +174,52 @@ struct GNUNET_GNS_Handle
237static void 174static void
238process_pending_messages (struct GNUNET_GNS_Handle *handle); 175process_pending_messages (struct GNUNET_GNS_Handle *handle);
239 176
240/**
241 * Try to (re)connect to the GNS service.
242 *
243 * @return GNUNET_YES on success, GNUNET_NO on failure.
244 */
245static int
246try_connect (struct GNUNET_GNS_Handle *handle)
247{
248 if (handle->client != NULL)
249 return GNUNET_OK;
250 handle->in_receive = GNUNET_NO;
251 handle->client = GNUNET_CLIENT_connect ("gns", handle->cfg);
252 if (handle->client == NULL)
253 {
254 LOG (GNUNET_ERROR_TYPE_WARNING,
255 _("Failed to connect to the GNS service!\n"));
256 return GNUNET_NO;
257 }
258 return GNUNET_YES;
259}
260
261/**
262 * Add the request corresponding to the given handle
263 * to the pending queue (if it is not already in there).
264 *
265 * @param cls the 'struct GNUNET_GNS_Handle*'
266 * @param key key for the request (not used)
267 * @param value the 'struct GNUNET_GNS_LookupHandle*'
268 * @return GNUNET_YES (always)
269 */
270static int
271add_lookup_request_to_pending (void *cls, const GNUNET_HashCode * key,
272 void *value)
273{
274 struct GNUNET_GNS_Handle *handle = cls;
275 struct GNUNET_GNS_LookupHandle *lh = value;
276
277 if (GNUNET_NO == lh->message->in_pending_queue)
278 {
279 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
280 "Retransmitting request related to %s to GNS %p\n", GNUNET_h2s(key),
281 handle);
282 GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
283 lh->message);
284 lh->message->in_pending_queue = GNUNET_YES;
285 }
286 return GNUNET_YES;
287}
288
289 177
290/** 178/**
291 * Add the request corresponding to the given handle 179 * Reconnect to GNS service.
292 * to the pending queue (if it is not already in there).
293 * 180 *
294 * @param cls the 'struct GNUNET_GNS_Handle*' 181 * @param h the handle to the namestore service
295 * @param key key for the request (not used)
296 * @param value the 'struct GNUNET_GNS_ShortenHandle*'
297 * @return GNUNET_YES (always)
298 */ 182 */
299static int 183static void
300add_shorten_request_to_pending (void *cls, const GNUNET_HashCode * key, 184reconnect (struct GNUNET_GNS_Handle *h)
301 void *value)
302{ 185{
303 struct GNUNET_GNS_Handle *handle = cls; 186 GNUNET_assert (NULL == h->client);
304 struct GNUNET_GNS_ShortenHandle *sh = value; 187 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
305 188 "Trying to connect to GNS...\n");
306 if (GNUNET_NO == sh->message->in_pending_queue) 189 h->client = GNUNET_CLIENT_connect ("gns", h->cfg);
307 { 190 GNUNET_assert (NULL != h->client);
308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
309 "Retransmitting shorten request related to %s to GNS %p\n",
310 GNUNET_h2s(key),
311 handle);
312 GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
313 sh->message);
314 sh->message->in_pending_queue = GNUNET_YES;
315 }
316 return GNUNET_YES;
317} 191}
318 192
319
320/** 193/**
321 * Try reconnecting to the GNS service. 194 * Reconnect to GNS
322 * 195 *
323 * @param cls GNUNET_GNS_Handle 196 * @param cls the handle
324 * @param tc scheduler context 197 * @param tc task context
325 */ 198 */
326static void 199static void
327try_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 200reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
328{ 201{
329 struct GNUNET_GNS_Handle *handle = cls; 202 struct GNUNET_GNS_Handle *h = cls;
330 203
331 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting with GNS %p\n", handle); 204 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
332 handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; 205 reconnect (h);
333 if (handle->retry_time.rel_value < GNUNET_CONSTANTS_SERVICE_RETRY.rel_value)
334 handle->retry_time = GNUNET_CONSTANTS_SERVICE_RETRY;
335 else
336 handle->retry_time = GNUNET_TIME_relative_multiply (handle->retry_time, 2);
337 if (handle->retry_time.rel_value > GNUNET_CONSTANTS_SERVICE_TIMEOUT.rel_value)
338 handle->retry_time = GNUNET_CONSTANTS_SERVICE_TIMEOUT;
339 handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
340 if (GNUNET_YES != try_connect (handle))
341 {
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS reconnect failed(!)\n");
343 return;
344 }
345 GNUNET_CONTAINER_multihashmap_iterate (handle->active_lookup_requests,
346 &add_lookup_request_to_pending, handle);
347 GNUNET_CONTAINER_multihashmap_iterate (handle->active_shorten_requests,
348 &add_shorten_request_to_pending, handle);
349 process_pending_messages (handle);
350} 206}
351 207
352 208
353/** 209/**
354 * Try reconnecting to the GNS service. 210 * Disconnect from service and then reconnect.
355 * 211 *
356 * @param handle handle to gns to (possibly) disconnect and reconnect 212 * @param h our handle
357 */ 213 */
358static void 214static void
359do_disconnect (struct GNUNET_GNS_Handle *handle) 215force_reconnect (struct GNUNET_GNS_Handle *h)
360{ 216{
361 if (handle->client == NULL) 217 h->reconnect = GNUNET_NO;
362 return; 218 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
363 GNUNET_assert (handle->reconnect_task == GNUNET_SCHEDULER_NO_TASK); 219 h->client = NULL;
364 if (NULL != handle->th) 220 h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
365 GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th); 221 &reconnect_task,
366 handle->th = NULL; 222 h);
367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
368 "Disconnecting from GNS service, will try to reconnect in %llu ms\n",
369 (unsigned long long) handle->retry_time.rel_value);
370 GNUNET_CLIENT_disconnect (handle->client, GNUNET_NO);
371 handle->client = NULL;
372 handle->reconnect_task =
373 GNUNET_SCHEDULER_add_delayed (handle->retry_time, &try_reconnect, handle);
374} 223}
375 224
376/** 225/**
@@ -386,7 +235,7 @@ transmit_pending (void *cls, size_t size, void *buf);
386 * @param msg the incoming message 235 * @param msg the incoming message
387 */ 236 */
388static void 237static void
389message_handler (void *cls, const struct GNUNET_MessageHeader *msg); 238process_message (void *cls, const struct GNUNET_MessageHeader *msg);
390 239
391/** 240/**
392 * Try to send messages from list of messages to send 241 * Try to send messages from list of messages to send
@@ -394,33 +243,35 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg);
394static void 243static void
395process_pending_messages (struct GNUNET_GNS_Handle *handle) 244process_pending_messages (struct GNUNET_GNS_Handle *handle)
396{ 245{
397 struct PendingMessage *head; 246 struct PendingMessage *p;
398 247
399 if (handle->client == NULL) 248 if (handle->client == NULL)
400 { 249 {
401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 250 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
402 "process_pending_messages called, but client is null, reconnecting\n"); 251 "process_pending_messages called, but client is null\n");
403 do_disconnect (handle);
404 return; 252 return;
405 } 253 }
406 254
407 if (handle->th != NULL) 255 if (handle->th != NULL)
408 return; 256 return;
409 257
410 if (NULL == (head = handle->pending_head)) 258 if (NULL == (p = handle->pending_head))
411 return; 259 return;
412 260
261 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
262 "Trying to transmit %d bytes...\n", p->size);
263
413 handle->th = 264 handle->th =
414 GNUNET_CLIENT_notify_transmit_ready (handle->client, 265 GNUNET_CLIENT_notify_transmit_ready (handle->client,
415 ntohs (head->msg->size), 266 p->size,
416 GNUNET_TIME_UNIT_FOREVER_REL, 267 GNUNET_TIME_UNIT_FOREVER_REL,
417 GNUNET_YES, &transmit_pending, 268 GNUNET_NO, &transmit_pending,
418 handle); 269 handle);
419 if (NULL != handle->th) 270 if (NULL != handle->th)
420 return; 271 return;
421 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 272
422 "notify_transmit_ready returned NULL, reconnecting\n"); 273 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
423 do_disconnect (handle); 274 "notify_transmit_ready returned NULL!\n");
424} 275}
425 276
426 277
@@ -431,53 +282,45 @@ static size_t
431transmit_pending (void *cls, size_t size, void *buf) 282transmit_pending (void *cls, size_t size, void *buf)
432{ 283{
433 struct GNUNET_GNS_Handle *handle = cls; 284 struct GNUNET_GNS_Handle *handle = cls;
434 struct PendingMessage *head; 285 struct PendingMessage *p;
435 size_t tsize; 286 size_t tsize;
287 char *cbuf;
436 288
437 handle->th = NULL; 289 handle->th = NULL;
438 290
439 if (buf == NULL) 291 if ((size == 0) || (buf == NULL))
440 { 292 {
441 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
442 "Transmission to GNS service failed! Reconnecting!\n"); 294 "Transmission to GNS service failed!\n");
443 do_disconnect (handle); 295 force_reconnect(handle);
444 return 0; 296 return 0;
445 } 297 }
446 298
447 if (NULL == (head = handle->pending_head)) 299 tsize = 0;
300 cbuf = buf;
301
302 if (NULL == (p = handle->pending_head))
448 return 0; 303 return 0;
449 304
450 tsize = ntohs (head->msg->size); 305 while ((NULL != (p = handle->pending_head)) && (p->size <= size))
451
452 if (size < tsize)
453 { 306 {
454 process_pending_messages (handle); 307 memcpy (&cbuf[tsize], &p[1], p->size);
455 return 0; 308 tsize += p->size;
309 size -= p->size;
310 GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, p);
311 if (GNUNET_YES != handle->in_receive)
312 {
313 GNUNET_CLIENT_receive (handle->client, &process_message, handle,
314 GNUNET_TIME_UNIT_FOREVER_REL);
315 handle->in_receive = GNUNET_YES;
316 }
317 GNUNET_free(p);
456 } 318 }
457
458 memcpy (buf, head->msg, tsize);
459
460 GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail,
461 head);
462
463 head->in_pending_queue = GNUNET_NO;
464
465 if (GNUNET_YES == head->free_on_send)
466 GNUNET_free (head);
467 319
468 process_pending_messages (handle);
469
470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 320 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
471 "Forwarded request of %u bytes to GNS service\n", (unsigned int) tsize); 321 "Sending %d bytes\n", tsize);
472 322
473 if (GNUNET_NO == handle->in_receive) 323 process_pending_messages(handle);
474 {
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476 "Starting to process replies from GNS\n");
477 handle->in_receive = GNUNET_YES;
478 GNUNET_CLIENT_receive (handle->client, &message_handler, handle,
479 GNUNET_TIME_UNIT_FOREVER_REL);
480 }
481 return tsize; 324 return tsize;
482} 325}
483 326
@@ -488,49 +331,32 @@ transmit_pending (void *cls, size_t size, void *buf)
488 * @param cls the 'struct GNUNET_GNS_ClientResultMessage' 331 * @param cls the 'struct GNUNET_GNS_ClientResultMessage'
489 * @param key query of the request 332 * @param key query of the request
490 * @param value the 'struct GNUNET_GNS_LookupHandle' of a request matching the same key 333 * @param value the 'struct GNUNET_GNS_LookupHandle' of a request matching the same key
491 * @return GNUNET_YES to continue to iterate over all results,
492 * GNUNET_NO if the reply is malformed
493 */ 334 */
494static int 335static void
495process_shorten_reply (void *cls, const GNUNET_HashCode * key, void *value) 336process_shorten_reply (struct GNUNET_GNS_QueueEntry *qe,
337 const struct GNUNET_GNS_ClientShortenResultMessage *msg)
496{ 338{
497 const struct GNUNET_GNS_ClientShortenResultMessage *gns_msg = cls; 339 struct GNUNET_GNS_Handle *h = qe->gns_handle;
498 struct GNUNET_GNS_ShortenHandle *shorten_handle = value;
499 const char *name = (const char*)&((struct GNUNET_GNS_ClientShortenMessage *) &((shorten_handle->message)[1]))[1]; //FIXME
500 const char *short_name; 340 const char *short_name;
501 341
502 if (ntohs (((struct GNUNET_MessageHeader*)gns_msg)->size) < 342 GNUNET_CONTAINER_DLL_remove(h->shorten_head, h->shorten_tail, qe);
343
344 short_name = (char*)(&msg[1]);
345
346 if (ntohs (((struct GNUNET_MessageHeader*)msg)->size) <
503 sizeof (struct GNUNET_GNS_ClientShortenResultMessage)) 347 sizeof (struct GNUNET_GNS_ClientShortenResultMessage))
504 { 348 {
505 GNUNET_break (0); 349 GNUNET_break (0);
506 do_disconnect (shorten_handle->gns_handle); 350 force_reconnect (h);
507 return GNUNET_NO; 351 return;
508 }
509
510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
511 "Received reply for `%s' from GNS service\n",
512 name);
513
514 if (gns_msg->unique_id != shorten_handle->unique_id)
515 {
516 /* UID mismatch */
517 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
518 "Ignoring reply for %s: UID mismatch: %llu/%llu\n", GNUNET_h2s (key),
519 gns_msg->unique_id, shorten_handle->unique_id);
520 return GNUNET_YES;
521 } 352 }
522 short_name = (char*)&gns_msg[1];
523 353
524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 354 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
525 "Giving shorten reply %s for %s to application\n", 355 "Received shortened reply `%s' from GNS service\n",
526 short_name, name); 356 short_name);
527 357
528 shorten_handle->proc (shorten_handle->proc_cls, name, short_name); 358 qe->proc(qe->proc_cls, short_name);
529 359
530 GNUNET_CLIENT_receive (shorten_handle->gns_handle->client,
531 &message_handler, shorten_handle->gns_handle,
532 GNUNET_TIME_UNIT_FOREVER_REL);
533 return GNUNET_YES;
534} 360}
535 361
536 362
@@ -543,48 +369,10 @@ process_shorten_reply (void *cls, const GNUNET_HashCode * key, void *value)
543 * @return GNUNET_YES to continue to iterate over all results, 369 * @return GNUNET_YES to continue to iterate over all results,
544 * GNUNET_NO if the reply is malformed 370 * GNUNET_NO if the reply is malformed
545 */ 371 */
546static int 372static void
547process_lookup_reply (void *cls, const GNUNET_HashCode * key, void *value) 373process_lookup_reply (struct GNUNET_GNS_QueueEntry *qe,
374 const struct GNUNET_GNS_ClientLookupResultMessage *msg)
548{ 375{
549 const struct GNUNET_GNS_ClientLookupResultMessage *gns_msg = cls;
550 struct GNUNET_GNS_LookupHandle *lookup_handle = value;
551 const char *name = (const char*) &lookup_handle[1];
552 struct GNUNET_NAMESTORE_RecordData *rd;
553 uint32_t rd_count;
554
555 if (ntohs (((struct GNUNET_MessageHeader*)gns_msg)->size) <
556 sizeof (struct GNUNET_GNS_ClientLookupResultMessage))
557 {
558 GNUNET_break (0);
559 do_disconnect (lookup_handle->gns_handle);
560 return GNUNET_NO;
561 }
562
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
564 "Received lookup reply for `%s' from GNS service %p\n",
565 name, lookup_handle->gns_handle);
566
567 if (gns_msg->unique_id != lookup_handle->unique_id)
568 {
569 /* UID mismatch */
570 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
571 "Ignoring reply for %s: UID mismatch: %llu/%llu\n", GNUNET_h2s (key),
572 gns_msg->unique_id, lookup_handle->unique_id);
573 return GNUNET_YES;
574 }
575
576 rd_count = ntohl(gns_msg->rd_count);
577 rd = (struct GNUNET_NAMESTORE_RecordData*)&gns_msg[1];
578 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
579 "Giving lookup reply for %s to application\n",
580 name);
581
582 lookup_handle->iter (lookup_handle->iter_cls, name, rd_count, rd);
583
584 GNUNET_CLIENT_receive (lookup_handle->gns_handle->client, &message_handler,
585 lookup_handle->gns_handle,
586 GNUNET_TIME_UNIT_FOREVER_REL);
587 return GNUNET_YES;
588} 376}
589 377
590/** 378/**
@@ -594,11 +382,15 @@ process_lookup_reply (void *cls, const GNUNET_HashCode * key, void *value)
594 * @param msg the incoming message 382 * @param msg the incoming message
595 */ 383 */
596static void 384static void
597message_handler (void *cls, const struct GNUNET_MessageHeader *msg) 385process_message (void *cls, const struct GNUNET_MessageHeader *msg)
598{ 386{
599 struct GNUNET_GNS_Handle *handle = cls; 387 struct GNUNET_GNS_Handle *handle = cls;
388 struct GNUNET_GNS_QueueEntry *qe;
600 const struct GNUNET_GNS_ClientLookupResultMessage *lookup_msg; 389 const struct GNUNET_GNS_ClientLookupResultMessage *lookup_msg;
601 const struct GNUNET_GNS_ClientShortenResultMessage *shorten_msg; 390 const struct GNUNET_GNS_ClientShortenResultMessage *shorten_msg;
391 uint16_t size;
392 uint16_t type;
393 uint32_t r_id;
602 394
603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 395 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
604 "Got message\n"); 396 "Got message\n");
@@ -606,36 +398,68 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
606 { 398 {
607 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 399 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
608 "Error receiving data from GNS service, reconnecting\n"); 400 "Error receiving data from GNS service, reconnecting\n");
609 do_disconnect (handle); 401 force_reconnect (handle);
610 return; 402 return;
611 } 403 }
612 404
613 if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT) 405 size = ntohs (msg->size);
406 type = ntohs (msg->type);
407
408 if (type == GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT)
614 { 409 {
615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
616 "Got lookup msg\n"); 411 "Got lookup msg\n");
617 lookup_msg = (const struct GNUNET_GNS_ClientLookupResultMessage *) msg; 412 lookup_msg = (const struct GNUNET_GNS_ClientLookupResultMessage *) msg;
618 GNUNET_CONTAINER_multihashmap_get_multiple (handle->active_lookup_requests, 413 r_id = ntohl (lookup_msg->id);
619 &lookup_msg->key, 414
620 &process_lookup_reply, 415 if (r_id > handle->r_id)
621 (void *) lookup_msg); 416 {
417 /** no request found */
418 GNUNET_break_op (0);
419 GNUNET_CLIENT_receive (handle->client, &process_message, handle,
420 GNUNET_TIME_UNIT_FOREVER_REL);
421 }
422
423 for (qe = handle->lookup_head; qe != NULL; qe = qe->next)
424 {
425 if (qe->r_id == r_id)
426 break;
427 }
428 if (qe)
429 process_lookup_reply(qe, lookup_msg);
430
431
622 } 432 }
623 else if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT) 433 else if (type == GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT)
624 { 434 {
625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 435 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
626 "Got shorten msg\n"); 436 "Got shorten msg\n");
627 shorten_msg = (const struct GNUNET_GNS_ClientShortenResultMessage *) msg; 437 shorten_msg = (struct GNUNET_GNS_ClientShortenResultMessage *) msg;
628 GNUNET_CONTAINER_multihashmap_get_multiple (handle->active_shorten_requests, 438
629 &shorten_msg->key, 439 r_id = ntohl (shorten_msg->id);
630 &process_shorten_reply, 440
631 (void *) shorten_msg); 441 if (r_id > handle->r_id)
632 } 442 {
633 else 443 /** no request found */
634 { 444 GNUNET_break_op (0);
635 GNUNET_break (0); 445 GNUNET_CLIENT_receive (handle->client, &process_message, handle,
636 do_disconnect (handle); 446 GNUNET_TIME_UNIT_FOREVER_REL);
637 return; 447 }
448
449 for (qe = handle->shorten_head; qe != NULL; qe = qe->next)
450 {
451 if (qe->r_id == r_id)
452 break;
453 }
454 if (qe)
455 process_shorten_reply(qe, shorten_msg);
638 } 456 }
457
458 GNUNET_CLIENT_receive (handle->client, &process_message, handle,
459 GNUNET_TIME_UNIT_FOREVER_REL);
460
461 if (GNUNET_YES == handle->reconnect)
462 force_reconnect (handle);
639 463
640} 464}
641 465
@@ -654,17 +478,10 @@ GNUNET_GNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
654 478
655 handle = GNUNET_malloc (sizeof (struct GNUNET_GNS_Handle)); 479 handle = GNUNET_malloc (sizeof (struct GNUNET_GNS_Handle));
656 handle->cfg = cfg; 480 handle->cfg = cfg;
657 handle->uid_gen = 481 reconnect (handle);
658 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); 482 //handle->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, handle);
659 handle->active_lookup_requests = 483 handle->r_id = 0;
660 GNUNET_CONTAINER_multihashmap_create (5); 484 handle->in_receive = GNUNET_NO;
661 handle->active_shorten_requests =
662 GNUNET_CONTAINER_multihashmap_create (5);
663 if (GNUNET_NO == try_connect (handle))
664 {
665 GNUNET_GNS_disconnect (handle);
666 return NULL;
667 }
668 return handle; 485 return handle;
669} 486}
670 487
@@ -680,6 +497,19 @@ GNUNET_GNS_disconnect (struct GNUNET_GNS_Handle *handle)
680 /* disco from GNS */ 497 /* disco from GNS */
681} 498}
682 499
500/*
501 * Helper function to generate request ids
502 *
503 * @param h handle
504 * @return a new id
505 */
506static uint32_t
507get_request_id (struct GNUNET_GNS_Handle *h)
508{
509 uint32_t r_id = h->r_id;
510 h->r_id++;
511 return r_id;
512}
683 513
684/** 514/**
685 * Perform an asynchronous Lookup operation on the GNS. 515 * Perform an asynchronous Lookup operation on the GNS.
@@ -690,67 +520,14 @@ GNUNET_GNS_disconnect (struct GNUNET_GNS_Handle *handle)
690 * @param iter_cls closure for iter 520 * @param iter_cls closure for iter
691 * @return handle to stop the async get 521 * @return handle to stop the async get
692 */ 522 */
693struct GNUNET_GNS_LookupHandle * 523struct GNUNET_GNS_QueueEntry *
694GNUNET_GNS_lookup_start (struct GNUNET_GNS_Handle *handle, 524GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
695 const char * name, 525 const char * name,
696 enum GNUNET_GNS_RecordType type, 526 enum GNUNET_GNS_RecordType type,
697 GNUNET_GNS_LookupIterator iter, 527 GNUNET_GNS_LookupIterator iter,
698 void *iter_cls) 528 void *iter_cls)
699{ 529{
700 /* IPC to look for local entries, start dht lookup, return lookup_handle */ 530 return NULL;
701 struct GNUNET_GNS_ClientLookupMessage *lookup_msg;
702 struct GNUNET_GNS_LookupHandle *lookup_handle;
703 GNUNET_HashCode key;
704 size_t msize;
705 struct PendingMessage *pending;
706
707 if (NULL == name)
708 {
709 return NULL;
710 }
711
712 GNUNET_CRYPTO_hash (name, strlen(name), &key);
713
714 msize = sizeof (struct GNUNET_GNS_ClientLookupMessage) + strlen(name);
715 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting lookup for %s in GNS %p\n",
716 name, handle);
717 pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize);
718 lookup_msg = (struct GNUNET_GNS_ClientLookupMessage *) &pending[1];
719 pending->msg = &lookup_msg->header;
720 pending->handle = handle;
721 pending->free_on_send = GNUNET_NO;
722 lookup_msg->header.size = htons (msize);
723 lookup_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_LOOKUP);
724 lookup_msg->key = key;
725 memcpy(&lookup_msg[1], name, strlen(name));
726 handle->uid_gen++;
727 lookup_msg->unique_id = handle->uid_gen;
728 GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
729 pending);
730 pending->in_pending_queue = GNUNET_YES;
731 lookup_handle = GNUNET_malloc (sizeof (struct GNUNET_GNS_LookupHandle));
732 lookup_handle->iter = iter;
733 lookup_handle->iter_cls = iter_cls;
734 lookup_handle->message = pending;
735 lookup_handle->unique_id = lookup_msg->unique_id;
736 GNUNET_CONTAINER_multihashmap_put (handle->active_lookup_requests,
737 &lookup_msg->key,
738 lookup_handle,
739 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
740 process_pending_messages (handle);
741 return lookup_handle;
742}
743
744
745/**
746 * Stop async GNS lookup.
747 *
748 * @param lookup_handle handle to the GNS lookup operation to stop
749 */
750void
751GNUNET_GNS_lookup_stop (struct GNUNET_GNS_LookupHandle *lookup_handle)
752{
753 /* TODO Stop gns lookups */
754} 531}
755 532
756 533
@@ -763,7 +540,7 @@ GNUNET_GNS_lookup_stop (struct GNUNET_GNS_LookupHandle *lookup_handle)
763 * @param proc_cls closure for processor 540 * @param proc_cls closure for processor
764 * @return handle to the operation 541 * @return handle to the operation
765 */ 542 */
766struct GNUNET_GNS_ShortenHandle * 543struct GNUNET_GNS_QueueEntry *
767GNUNET_GNS_shorten (struct GNUNET_GNS_Handle *handle, 544GNUNET_GNS_shorten (struct GNUNET_GNS_Handle *handle,
768 const char * name, 545 const char * name,
769 GNUNET_GNS_ShortenResultProcessor proc, 546 GNUNET_GNS_ShortenResultProcessor proc,
@@ -771,7 +548,7 @@ GNUNET_GNS_shorten (struct GNUNET_GNS_Handle *handle,
771{ 548{
772 /* IPC to shorten gns names, return shorten_handle */ 549 /* IPC to shorten gns names, return shorten_handle */
773 struct GNUNET_GNS_ClientShortenMessage *shorten_msg; 550 struct GNUNET_GNS_ClientShortenMessage *shorten_msg;
774 struct GNUNET_GNS_ShortenHandle *shorten_handle; 551 struct GNUNET_GNS_QueueEntry *qe;
775 size_t msize; 552 size_t msize;
776 struct PendingMessage *pending; 553 struct PendingMessage *pending;
777 554
@@ -780,33 +557,34 @@ GNUNET_GNS_shorten (struct GNUNET_GNS_Handle *handle,
780 return NULL; 557 return NULL;
781 } 558 }
782 559
783 msize = sizeof (struct GNUNET_GNS_ClientShortenMessage) + strlen(name) +1; 560 msize = sizeof (struct GNUNET_GNS_ClientShortenMessage) + strlen(name) + 1;
784 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to shorten %s in GNS\n", name); 561 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to shorten %s in GNS\n", name);
562
563 qe = GNUNET_malloc(sizeof (struct GNUNET_GNS_QueueEntry));
564 qe->gns_handle = handle;
565 qe->proc = proc;
566 qe->proc_cls = proc_cls;
567 qe->r_id = get_request_id(handle);
568 GNUNET_CONTAINER_DLL_insert_tail(handle->shorten_head,
569 handle->shorten_tail, qe);
570
785 pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); 571 pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize);
786 memset(pending, 0, (sizeof (struct PendingMessage) + msize)); 572 memset(pending, 0, (sizeof (struct PendingMessage) + msize));
573
574 pending->size = msize;
575
787 shorten_msg = (struct GNUNET_GNS_ClientShortenMessage *) &pending[1]; 576 shorten_msg = (struct GNUNET_GNS_ClientShortenMessage *) &pending[1];
788 pending->msg = &shorten_msg->header;
789 pending->handle = handle;
790 pending->free_on_send = GNUNET_NO;
791 shorten_msg->header.size = htons (msize);
792 shorten_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_SHORTEN); 577 shorten_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_SHORTEN);
578 shorten_msg->header.size = htons (msize);
579 shorten_msg->id = htonl(qe->r_id);
580
793 memcpy(&shorten_msg[1], name, strlen(name)); 581 memcpy(&shorten_msg[1], name, strlen(name));
794 handle->uid_gen++; 582
795 shorten_msg->unique_id = handle->uid_gen;
796 GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, 583 GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
797 pending); 584 pending);
798 pending->in_pending_queue = GNUNET_YES; 585
799 shorten_handle = GNUNET_malloc (sizeof (struct GNUNET_GNS_ShortenHandle));
800 shorten_handle->proc = proc;
801 shorten_handle->proc_cls = proc_cls;
802 shorten_handle->message = pending;
803 shorten_handle->unique_id = shorten_msg->unique_id;
804 GNUNET_CONTAINER_multihashmap_put (handle->active_shorten_requests,
805 &shorten_msg->key,
806 shorten_handle,
807 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
808 process_pending_messages (handle); 586 process_pending_messages (handle);
809 return shorten_handle; 587 return qe;
810} 588}
811 589
812 590