-doxygen
[oweals/gnunet.git] / src / gns / gns_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010, 2012 Christian Grothoff (and other contributing authors)
4
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
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file gns/gns_api.c
22  * @brief library to access the GNS service
23  * @author Martin Schanzenbach
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_arm_service.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_dht_service.h"
33 #include "gns.h"
34 #include "gnunet_gns_service.h"
35
36
37 /**
38  * Handle to a lookup request
39  */
40 struct GNUNET_GNS_LookupRequest
41 {
42
43   /**
44    * DLL
45    */
46   struct GNUNET_GNS_LookupRequest *next;
47   
48   /**
49    * DLL
50    */
51   struct GNUNET_GNS_LookupRequest *prev;
52   
53   /**
54    * handle to gns 
55    */
56   struct GNUNET_GNS_Handle *gns_handle;
57   
58   /**
59    * processor to call on lookup result 
60    */
61   GNUNET_GNS_LookupResultProcessor lookup_proc;
62
63   /**
64    * processor closure 
65    */
66   void *proc_cls;
67  
68   /**
69    * request id 
70    */
71   uint32_t r_id;
72  
73 };
74
75
76 /**
77  * Handle to a shorten request
78  */
79 struct GNUNET_GNS_ShortenRequest
80 {
81   /**
82    * DLL
83    */
84   struct GNUNET_GNS_ShortenRequest *next;
85   
86   /**
87    * DLL
88    */
89   struct GNUNET_GNS_ShortenRequest *prev;
90
91   /**
92    * handle to gns
93    */
94   struct GNUNET_GNS_Handle *gns_handle;
95   
96   /**
97    *  processor to call on shorten result
98    */
99   GNUNET_GNS_ShortenResultProcessor shorten_proc;
100   
101   /**
102    * processor closure
103    */
104   void *proc_cls;
105
106   /**
107    * request id
108    */
109   uint32_t r_id;
110   
111 };
112
113
114 /**
115  * Handle to GetAuthorityRequest
116  */
117 struct GNUNET_GNS_GetAuthRequest
118 {
119   /**
120    * DLL
121    */
122   struct GNUNET_GNS_GetAuthRequest *next;
123   
124   /**
125    * DLL
126    */
127   struct GNUNET_GNS_GetAuthRequest *prev;
128
129   /**
130    * handle to gns
131    */
132   struct GNUNET_GNS_Handle *gns_handle;
133   
134   /**
135    * processor to call on authority lookup result
136    */
137   GNUNET_GNS_GetAuthResultProcessor auth_proc;
138   
139   /**
140    * processor closure
141    */
142   void *proc_cls;
143   
144   /**
145    * request id
146    */
147   uint32_t r_id;
148   
149 };
150
151
152 /**
153  * Entry in our list of messages to be (re-)transmitted.
154  */
155 struct PendingMessage
156 {
157   /**
158    * This is a doubly-linked list.
159    */
160   struct PendingMessage *prev;
161
162   /**
163    * This is a doubly-linked list.
164    */
165   struct PendingMessage *next;
166
167   /**
168    * Size of the message.
169    */
170   size_t size;
171
172   /**
173    * request id
174    */
175   uint32_t r_id;
176
177   /**
178    * This message has been transmitted.  GNUNET_NO if the message is
179    * in the "pending" DLL, GNUNET_YES if it has been transmitted to
180    * the service via the current client connection.
181    */
182   int transmitted;
183
184 };
185
186
187 /**
188  * Connection to the GNS service.
189  */
190 struct GNUNET_GNS_Handle
191 {
192
193   /**
194    * Configuration to use.
195    */
196   const struct GNUNET_CONFIGURATION_Handle *cfg;
197
198   /**
199    * Socket (if available).
200    */
201   struct GNUNET_CLIENT_Connection *client;
202
203   /**
204    * Currently pending transmission request (or NULL).
205    */
206   struct GNUNET_CLIENT_TransmitHandle *th;
207   
208   /**
209    * Head of linked list of shorten messages we would like to transmit.
210    */
211   struct PendingMessage *pending_head;
212
213   /**
214    * Tail of linked list of shorten messages we would like to transmit.
215    */
216   struct PendingMessage *pending_tail;
217   
218   /**
219    * Head of linked list of shorten messages we would like to transmit.
220    */
221   struct GNUNET_GNS_ShortenRequest *shorten_head;
222
223   /**
224    * Tail of linked list of shorten messages we would like to transmit.
225    */
226   struct GNUNET_GNS_ShortenRequest *shorten_tail;
227   
228   /**
229    * Head of linked list of lookup messages we would like to transmit.
230    */
231   struct GNUNET_GNS_LookupRequest *lookup_head;
232
233   /**
234    * Tail of linked list of lookup messages we would like to transmit.
235    */
236   struct GNUNET_GNS_LookupRequest *lookup_tail;
237   
238   /**
239    * Head of linked list of authority lookup messages we would like to transmit.
240    */
241   struct GNUNET_GNS_GetAuthRequest *get_auth_head;
242
243   /**
244    * Tail of linked list of authority lookup messages we would like to transmit.
245    */
246   struct GNUNET_GNS_GetAuthRequest *get_auth_tail;
247
248   /**
249    * Reconnect task
250    */
251   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
252   
253   /**
254    * How long do we wait until we try to reconnect?
255    */
256   struct GNUNET_TIME_Relative reconnect_backoff;
257
258   /**
259    * Request Id generator.  Incremented by one for each request.
260    */
261   uint32_t r_id_gen;
262   
263   /**
264    * Did we start our receive loop yet?
265    */
266   int in_receive;
267
268 };
269
270
271 /**
272  * Try to send messages from list of messages to send
273  * @param handle GNS_Handle
274  */
275 static void
276 process_pending_messages (struct GNUNET_GNS_Handle *handle);
277
278
279 /**
280  * Reconnect to GNS service.
281  *
282  * @param handle the handle to the GNS service
283  */
284 static void
285 reconnect (struct GNUNET_GNS_Handle *handle)
286 {
287   GNUNET_assert (NULL == handle->client);
288   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
289               "Trying to connect to GNS\n");
290   handle->client = GNUNET_CLIENT_connect ("gns", handle->cfg);
291   GNUNET_assert (NULL != handle->client);
292   process_pending_messages (handle);
293 }
294
295
296 /**
297  * Reconnect to GNS
298  *
299  * @param cls the handle
300  * @param tc task context
301  */
302 static void
303 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
304 {
305   struct GNUNET_GNS_Handle *handle = cls;
306
307   handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
308   reconnect (handle);
309 }
310
311
312 /**
313  * Disconnect from service and then reconnect.
314  *
315  * @param handle our handle
316  */
317 static void
318 force_reconnect (struct GNUNET_GNS_Handle *handle)
319 {
320   struct GNUNET_GNS_ShortenRequest *st;
321   struct GNUNET_GNS_LookupRequest *lh;
322   struct GNUNET_GNS_GetAuthRequest *ga;
323   struct PendingMessage *p;
324
325   GNUNET_CLIENT_disconnect (handle->client);
326   handle->client = NULL;
327   handle->in_receive = GNUNET_NO;
328   for (st = handle->shorten_head; NULL != st; st = st->next)
329   {
330     p = (struct PendingMessage *) &st[1];
331     if (GNUNET_NO == p->transmitted)
332       continue;
333     p->transmitted = GNUNET_NO;
334     GNUNET_CONTAINER_DLL_insert (handle->pending_head,
335                                  handle->pending_tail,
336                                  p);  
337   }
338   for (lh = handle->lookup_head; NULL != lh; lh = lh->next)
339   {
340     p = (struct PendingMessage *) &lh[1];
341     if (GNUNET_NO == p->transmitted)
342       continue;
343     p->transmitted = GNUNET_NO;
344     GNUNET_CONTAINER_DLL_insert (handle->pending_head,
345                                  handle->pending_tail,
346                                  p);  
347   }
348   for (ga = handle->get_auth_head; NULL != ga; ga = ga->next)
349   {
350     p = (struct PendingMessage *) &ga[1];
351     if (GNUNET_NO == p->transmitted)
352       continue;
353     p->transmitted = GNUNET_NO;
354     GNUNET_CONTAINER_DLL_insert (handle->pending_head,
355                                  handle->pending_tail,
356                                  p);  
357   }
358   handle->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
359   handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
360                                                     &reconnect_task,
361                                                     handle);
362 }
363
364
365 /**
366  * Transmit the next pending message, called by notify_transmit_ready
367  *
368  * @param cls the closure
369  * @param size size of pending data
370  * @param buf buffer with pending data
371  * @return size data transmitted
372  */
373 static size_t
374 transmit_pending (void *cls, size_t size, void *buf);
375
376
377 /**
378  * Handler for messages received from the GNS service
379  *
380  * @param cls the 'struct GNUNET_GNS_Handle'
381  * @param msg the incoming message
382  */
383 static void
384 process_message (void *cls, const struct GNUNET_MessageHeader *msg);
385
386
387 /**
388  * Try to send messages from list of messages to send
389  *
390  * @param handle the GNS handle
391  */
392 static void
393 process_pending_messages (struct GNUNET_GNS_Handle *handle)
394 {
395   struct PendingMessage *p = handle->pending_head;
396
397   if (NULL == handle->client)
398     return; /* wait for reconnect */ 
399   if (NULL != handle->th)
400     return; /* transmission request already pending */ 
401
402   while ((NULL != p) && (p->transmitted == GNUNET_YES))
403     p = p->next;
404   if (NULL == p)
405     return; /* no messages pending */
406   
407   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
408               "Trying to transmit %u bytes\n", 
409               (unsigned int) p->size);
410   handle->th =
411     GNUNET_CLIENT_notify_transmit_ready (handle->client,
412                                          p->size,
413                                          GNUNET_TIME_UNIT_FOREVER_REL,
414                                          GNUNET_NO, &transmit_pending,
415                                          handle);
416   GNUNET_break (NULL != handle->th);
417 }
418
419
420 /**
421  * Transmit the next pending message, called by notify_transmit_ready
422  *
423  * @param cls the closure
424  * @param size size of pending data
425  * @param buf buffer with pending data
426  * @return size data transmitted
427  */
428 static size_t
429 transmit_pending (void *cls, size_t size, void *buf)
430 {
431   struct GNUNET_GNS_Handle *handle = cls;
432   char *cbuf = buf;
433   struct PendingMessage *p;
434   size_t tsize;
435
436   handle->th = NULL;
437   if ((0 == size) || (NULL == buf))
438   {
439     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
440                 "Transmission to GNS service failed!\n");
441     force_reconnect (handle);
442     return 0;
443   }  
444   if (NULL == (p = handle->pending_head))
445     return 0;
446
447   tsize = 0;
448   while ((NULL != (p = handle->pending_head)) && (p->size <= size))
449   {
450     memcpy (&cbuf[tsize], &p[1], p->size);
451     tsize += p->size;
452     size -= p->size;
453     p->transmitted = GNUNET_YES;
454     GNUNET_CONTAINER_DLL_remove (handle->pending_head,
455                                  handle->pending_tail,
456                                  p);
457     if (GNUNET_YES != handle->in_receive)
458     {
459       GNUNET_CLIENT_receive (handle->client, &process_message, handle,
460                              GNUNET_TIME_UNIT_FOREVER_REL);
461       handle->in_receive = GNUNET_YES;
462     }
463   }
464   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
465               "Sending %u bytes\n",
466               (unsigned int) tsize);
467   process_pending_messages (handle);
468   return tsize;
469 }
470
471
472 /**
473  * Process a given reply that might match the given
474  * request.
475  *
476  * @param qe a queue entry
477  * @param msg the shorten msg received
478  */
479 static void
480 process_shorten_reply (struct GNUNET_GNS_ShortenRequest *qe,
481                        const struct GNUNET_GNS_ClientShortenResultMessage *msg)
482 {
483   struct GNUNET_GNS_Handle *handle = qe->gns_handle;
484   struct PendingMessage *p = (struct PendingMessage *)&qe[1];
485   const char *short_name;
486   size_t mlen;
487   
488   if (GNUNET_YES != p->transmitted)
489   {
490     /* service send reply to query we never managed to send!? */
491     GNUNET_break (0);
492     force_reconnect (handle);
493     return;
494   }
495   mlen = ntohs (msg->header.size);
496   if (ntohs (msg->header.size) == sizeof (struct GNUNET_GNS_ClientShortenResultMessage))
497   {
498     /* service reports resolution failed */
499     short_name = NULL;
500   }
501   else
502   {
503     short_name = (const char *) &msg[1];
504     if ('\0' != short_name[mlen - sizeof (struct GNUNET_GNS_ClientShortenResultMessage) - 1])
505     {
506       GNUNET_break (0);
507       force_reconnect (handle);
508       return;
509     } 
510   }
511   GNUNET_CONTAINER_DLL_remove (handle->shorten_head, handle->shorten_tail, qe);
512   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
513               "Received shortened reply `%s' from GNS service\n",
514               short_name);
515   qe->shorten_proc (qe->proc_cls, short_name);
516   GNUNET_free (qe);
517 }
518
519
520 /**
521  * Process a given reply that might match the given
522  * request.
523  *
524  * @param qe the handle to the request
525  * @param msg the message to process
526  */
527 static void
528 process_get_auth_reply (struct GNUNET_GNS_GetAuthRequest *qe,
529                        const struct GNUNET_GNS_ClientGetAuthResultMessage *msg)
530 {
531   struct GNUNET_GNS_Handle *handle = qe->gns_handle;
532   struct PendingMessage *p = (struct PendingMessage *)&qe[1];
533   const char *auth_name;
534   size_t mlen;
535
536   if (GNUNET_YES != p->transmitted)
537   {
538     /* service send reply to query we never managed to send!? */
539     GNUNET_break (0);
540     force_reconnect (handle);
541     return;
542   }
543   mlen = ntohs (msg->header.size);
544   if (mlen == sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage))
545   {
546     auth_name = NULL;
547   }
548   else
549   {
550     auth_name = (const char*) &msg[1];
551     if ('\0' != auth_name[mlen - sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage) - 1])
552     {
553       GNUNET_break (0);
554       force_reconnect (handle);
555       return;
556     }
557   }
558   GNUNET_CONTAINER_DLL_remove (handle->get_auth_head, handle->get_auth_tail, qe);
559   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
560               "Received GET_AUTH reply `%s' from GNS service\n",
561               auth_name);
562   qe->auth_proc (qe->proc_cls, auth_name);
563   GNUNET_free (qe);
564 }
565
566
567 /**
568  * Process a given reply to the lookup request
569  *
570  * @param qe a queue entry
571  * @param msg the lookup message received
572  */
573 static void
574 process_lookup_reply (struct GNUNET_GNS_LookupRequest *qe,
575                       const struct GNUNET_GNS_ClientLookupResultMessage *msg)
576 {
577   struct GNUNET_GNS_Handle *handle = qe->gns_handle;
578   struct PendingMessage *p = (struct PendingMessage *) &qe[1];
579   uint32_t rd_count = ntohl (msg->rd_count);
580   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
581   size_t mlen;
582
583   if (GNUNET_YES != p->transmitted)
584   {
585     /* service send reply to query we never managed to send!? */
586     GNUNET_break (0);
587     force_reconnect (handle);
588     return;
589   }
590   mlen = ntohs (msg->header.size);
591   mlen -= sizeof (struct GNUNET_GNS_ClientLookupResultMessage);
592   if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (mlen,
593                                                              (const char*) &msg[1],
594                                                              rd_count,
595                                                              rd))
596   {
597     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
598                 _("Failed to serialize lookup reply from GNS service!\n"));
599     qe->lookup_proc (qe->proc_cls, 0, NULL);
600   }
601   else
602   { 
603     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
604                 "Received lookup reply from GNS service (%u records)\n",
605                 (unsigned int) rd_count);
606     qe->lookup_proc (qe->proc_cls, rd_count, rd);
607   }
608   GNUNET_CONTAINER_DLL_remove (handle->lookup_head, handle->lookup_tail, qe);
609   GNUNET_free (qe);
610 }
611
612
613 /**
614  * Handler for messages received from the GNS service
615  *
616  * @param cls the 'struct GNUNET_GNS_Handle'
617  * @param msg the incoming message
618  */
619 static void
620 process_message (void *cls, const struct GNUNET_MessageHeader *msg)
621 {
622   struct GNUNET_GNS_Handle *handle = cls;
623   struct GNUNET_GNS_LookupRequest *lr;
624   struct GNUNET_GNS_ShortenRequest *sr;
625   struct GNUNET_GNS_GetAuthRequest *gar;
626   const struct GNUNET_GNS_ClientLookupResultMessage *lookup_msg;
627   const struct GNUNET_GNS_ClientShortenResultMessage *shorten_msg;
628   const struct GNUNET_GNS_ClientGetAuthResultMessage *get_auth_msg;
629   uint32_t r_id;
630   
631   if (NULL == msg)
632   {
633     force_reconnect (handle);
634     return;
635   }
636   switch (ntohs (msg->type))
637   {
638   case GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT:
639     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
640                 "Got LOOKUP_RESULT msg\n");
641     if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientLookupResultMessage))
642     {
643       GNUNET_break (0);
644       force_reconnect (handle);
645       return;
646     }
647     lookup_msg = (const struct GNUNET_GNS_ClientLookupResultMessage *) msg;
648     r_id = ntohl (lookup_msg->id);   
649     for (lr = handle->lookup_head; NULL != lr; lr = lr->next)    
650       if (lr->r_id == r_id)
651       {
652         process_lookup_reply(lr, lookup_msg);    
653         break;
654       }
655     break;
656   case GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT:  
657     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
658                 "Got SHORTEN_RESULT msg\n");
659     if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientShortenResultMessage))
660     {
661       GNUNET_break (0);
662       force_reconnect (handle);
663       return;
664     }
665     shorten_msg = (const struct GNUNET_GNS_ClientShortenResultMessage *) msg;   
666     r_id = ntohl (shorten_msg->id);
667     for (sr = handle->shorten_head; NULL != sr; sr = sr->next)    
668       if (sr->r_id == r_id)
669       {
670         process_shorten_reply (sr, shorten_msg);
671         break;
672       }
673     break;
674   case GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT:
675     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
676                 "Got GET_AUTH_RESULT msg\n");
677     if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage))
678     {
679       GNUNET_break (0);
680       force_reconnect (handle);
681       return;
682     }
683     get_auth_msg = (const struct GNUNET_GNS_ClientGetAuthResultMessage *) msg;
684     r_id = ntohl (get_auth_msg->id);
685     for (gar = handle->get_auth_head; NULL != gar; gar = gar->next)
686       if (gar->r_id == r_id)
687       {
688         process_get_auth_reply (gar, get_auth_msg);
689         break;
690       }
691     break;
692   default:
693     GNUNET_break (0);
694     force_reconnect (handle);
695     return;
696   }
697   GNUNET_CLIENT_receive (handle->client, &process_message, handle,
698                          GNUNET_TIME_UNIT_FOREVER_REL);
699 }
700
701
702 /**
703  * Initialize the connection with the GNS service.
704  *
705  * @param cfg configuration to use
706  * @return handle to the GNS service, or NULL on error
707  */
708 struct GNUNET_GNS_Handle *
709 GNUNET_GNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
710 {
711   struct GNUNET_GNS_Handle *handle;
712
713   handle = GNUNET_malloc (sizeof (struct GNUNET_GNS_Handle));
714   handle->cfg = cfg;
715   reconnect (handle);
716   return handle;
717 }
718
719
720 /**
721  * Shutdown connection with the GNS service.
722  *
723  * @param handle handle of the GNS connection to stop
724  */
725 void
726 GNUNET_GNS_disconnect (struct GNUNET_GNS_Handle *handle)
727 {
728   GNUNET_CLIENT_disconnect (handle->client);
729   if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
730   {
731     GNUNET_SCHEDULER_cancel (handle->reconnect_task);
732     handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
733   }
734   GNUNET_assert (NULL == handle->lookup_head);
735   GNUNET_assert (NULL == handle->shorten_head);
736   GNUNET_assert (NULL == handle->get_auth_head);
737   GNUNET_free (handle);
738 }
739
740
741 /**
742  * Cancel pending lookup request
743  *
744  * @param lr the lookup request to cancel
745  */
746 void
747 GNUNET_GNS_cancel_lookup_request (struct GNUNET_GNS_LookupRequest *lr)
748 {
749   struct PendingMessage *p = (struct PendingMessage*) &lr[1];
750
751   GNUNET_assert (NULL != lr->gns_handle); 
752   if (GNUNET_NO == p->transmitted)
753     GNUNET_CONTAINER_DLL_remove (lr->gns_handle->pending_head,
754                                  lr->gns_handle->pending_tail,
755                                  p);
756   GNUNET_CONTAINER_DLL_remove (lr->gns_handle->lookup_head,
757                                lr->gns_handle->lookup_tail,
758                                lr);
759   GNUNET_free (lr);
760 }
761
762
763 /**
764  * Cancel pending shorten request
765  *
766  * @param sr the lookup request to cancel
767  */
768 void
769 GNUNET_GNS_cancel_shorten_request (struct GNUNET_GNS_ShortenRequest *sr)
770 {
771   struct PendingMessage *p = (struct PendingMessage*) &sr[1];
772
773   GNUNET_assert (NULL != sr->gns_handle);
774   if (GNUNET_NO == p->transmitted)
775     GNUNET_CONTAINER_DLL_remove (sr->gns_handle->pending_head,
776                                  sr->gns_handle->pending_tail,
777                                  p);
778   GNUNET_CONTAINER_DLL_remove (sr->gns_handle->shorten_head,
779                                sr->gns_handle->shorten_tail,
780                                sr);
781   GNUNET_free (sr);
782 }
783
784
785 /**
786  * Cancel pending get auth  request
787  *
788  * @param gar the lookup request to cancel
789  */
790 void
791 GNUNET_GNS_cancel_get_auth_request (struct GNUNET_GNS_GetAuthRequest *gar)
792 {
793   struct PendingMessage *p = (struct PendingMessage*) &gar[1];
794
795   GNUNET_assert (NULL != gar->gns_handle); 
796   if (GNUNET_NO == p->transmitted)
797     GNUNET_CONTAINER_DLL_remove (gar->gns_handle->pending_head,
798                                  gar->gns_handle->pending_tail,
799                                  p);  
800   GNUNET_CONTAINER_DLL_remove (gar->gns_handle->get_auth_head,
801                                gar->gns_handle->get_auth_tail,
802                                gar);
803   GNUNET_free (gar);
804 }
805
806
807 /**
808  * Perform an asynchronous Lookup operation on the GNS.
809  *
810  * @param handle handle to the GNS service
811  * @param name the name to look up
812  * @param zone the zone to start the resolution in
813  * @param type the record type to look up
814  * @param only_cached GNUNET_YES to only check locally not DHT for performance
815  * @param shorten_key the private key of the shorten zone (can be NULL)
816  * @param proc processor to call on result
817  * @param proc_cls closure for processor
818  * @return handle to the get request
819  */
820 struct GNUNET_GNS_LookupRequest*
821 GNUNET_GNS_lookup_zone (struct GNUNET_GNS_Handle *handle,
822                         const char *name,
823                         struct GNUNET_CRYPTO_ShortHashCode *zone,
824                         enum GNUNET_GNS_RecordType type,
825                         int only_cached,
826                         struct GNUNET_CRYPTO_RsaPrivateKey *shorten_key,
827                         GNUNET_GNS_LookupResultProcessor proc,
828                         void *proc_cls)
829 {
830   /* IPC to shorten gns names, return shorten_handle */
831   struct GNUNET_GNS_ClientLookupMessage *lookup_msg;
832   struct GNUNET_GNS_LookupRequest *lr;
833   size_t msize;
834   struct PendingMessage *pending;
835   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *pkey_enc;
836   size_t key_len;
837   char* pkey_tmp;
838
839   if (NULL == name)
840   {
841     GNUNET_break (0);
842     return NULL;
843   } 
844   if (NULL != shorten_key)
845   {
846     pkey_enc = GNUNET_CRYPTO_rsa_encode_key (shorten_key);
847     GNUNET_assert (pkey_enc != NULL);
848     key_len = ntohs (pkey_enc->len);
849   }
850   else
851   {
852     pkey_enc = NULL;
853     key_len = 0;
854   }
855   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
856               "Trying to lookup `%s' in GNS\n", 
857               name);
858   msize = sizeof (struct GNUNET_GNS_ClientLookupMessage)
859     + key_len + strlen (name) + 1;
860   if (msize > UINT16_MAX)
861   {
862     GNUNET_break (0);
863     GNUNET_free (pkey_enc);
864     return NULL;
865   }
866   lr = GNUNET_malloc (sizeof (struct GNUNET_GNS_LookupRequest) +
867                       sizeof (struct PendingMessage) + msize);
868   lr->gns_handle = handle;
869   lr->lookup_proc = proc;
870   lr->proc_cls = proc_cls;
871   lr->r_id = handle->r_id_gen++;
872   pending = (struct PendingMessage *)&lr[1];
873   pending->size = msize;
874   pending->r_id = lr->r_id;
875   GNUNET_CONTAINER_DLL_insert_tail (handle->lookup_head,
876                                     handle->lookup_tail, lr);
877
878   lookup_msg = (struct GNUNET_GNS_ClientLookupMessage *) &pending[1];
879   lookup_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_LOOKUP);
880   lookup_msg->header.size = htons (msize);
881   lookup_msg->id = htonl (lr->r_id);
882   lookup_msg->only_cached = htonl (only_cached);
883   if (NULL != zone)
884   {
885     lookup_msg->use_default_zone = htonl (GNUNET_NO);
886     memcpy (&lookup_msg->zone, zone, sizeof (struct GNUNET_CRYPTO_ShortHashCode));
887   }
888   else
889   {
890     lookup_msg->use_default_zone = htonl (GNUNET_YES);
891     memset (&lookup_msg->zone, 0, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
892   }  
893   lookup_msg->type = htonl (type);
894   pkey_tmp = (char *) &lookup_msg[1];  
895   if (pkey_enc != NULL)
896   {
897     lookup_msg->have_key = htonl (GNUNET_YES);
898     memcpy (pkey_tmp, pkey_enc, key_len);
899   }
900   else
901     lookup_msg->have_key = htonl (GNUNET_NO);
902   GNUNET_free_non_null (pkey_enc);
903   memcpy (&pkey_tmp[key_len], name, strlen (name) + 1);
904
905   GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head,
906                                     handle->pending_tail,
907                                     pending);
908   process_pending_messages (handle);
909   return lr;
910 }
911
912
913 /**
914  * Perform an asynchronous Lookup operation on the GNS.
915  *
916  * @param handle handle to the GNS service
917  * @param name the name to look up
918  * @param type the record type to look up
919  * @param only_cached GNUNET_YES to only check locally not DHT for performance
920  * @param shorten_key the private key of the shorten zone (can be NULL)
921  * @param proc processor to call on result
922  * @param proc_cls closure for processor
923  * @return handle to the lookup request
924  */
925 struct GNUNET_GNS_LookupRequest *
926 GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
927                    const char *name,
928                    enum GNUNET_GNS_RecordType type,
929                    int only_cached,
930                    struct GNUNET_CRYPTO_RsaPrivateKey *shorten_key,
931                    GNUNET_GNS_LookupResultProcessor proc,
932                    void *proc_cls)
933 {
934   return GNUNET_GNS_lookup_zone (handle, name,
935                                  NULL,
936                                  type, only_cached,
937                                  shorten_key,
938                                  proc, proc_cls);
939 }
940
941
942 /**
943  * Perform a name shortening operation on the GNS.
944  *
945  * @param handle handle to the GNS service
946  * @param name the name to look up
947  * @param private_zone the public zone of the private zone
948  * @param shorten_zone the public zone of the shorten zone
949  * @param zone the zone to start the resolution in
950  * @param proc function to call on result
951  * @param proc_cls closure for processor
952  * @return handle to the operation
953  */
954 struct GNUNET_GNS_ShortenRequest*
955 GNUNET_GNS_shorten_zone (struct GNUNET_GNS_Handle *handle,
956                          const char *name,
957                          struct GNUNET_CRYPTO_ShortHashCode *private_zone,
958                          struct GNUNET_CRYPTO_ShortHashCode *shorten_zone,
959                          struct GNUNET_CRYPTO_ShortHashCode *zone,
960                          GNUNET_GNS_ShortenResultProcessor proc,
961                          void *proc_cls)
962 {
963   /* IPC to shorten gns names, return shorten_handle */
964   struct GNUNET_GNS_ClientShortenMessage *shorten_msg;
965   struct GNUNET_GNS_ShortenRequest *sr;
966   size_t msize;
967   struct PendingMessage *pending;
968
969   if (NULL == name)
970   {
971     GNUNET_break (0);
972     return NULL;
973   }
974   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to shorten `%s' in GNS\n", name);
975   msize = sizeof (struct GNUNET_GNS_ClientShortenMessage) + strlen (name) + 1;
976   if (msize > UINT16_MAX)
977   {
978     GNUNET_break (0);
979     return NULL;
980   }
981   sr = GNUNET_malloc (sizeof (struct GNUNET_GNS_ShortenRequest) +
982                       sizeof (struct PendingMessage) + msize);
983   sr->gns_handle = handle;
984   sr->shorten_proc = proc;
985   sr->proc_cls = proc_cls;
986   sr->r_id = handle->r_id_gen++;
987   GNUNET_CONTAINER_DLL_insert_tail (handle->shorten_head,
988                                     handle->shorten_tail, sr);
989   pending = (struct PendingMessage *)&sr[1];
990   pending->size = msize;
991   pending->r_id = sr->r_id;
992
993   shorten_msg = (struct GNUNET_GNS_ClientShortenMessage *) &pending[1];
994   shorten_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_SHORTEN);
995   shorten_msg->header.size = htons ((uint16_t) msize);
996   shorten_msg->id = htonl (sr->r_id);
997   shorten_msg->private_zone = *private_zone;
998   shorten_msg->shorten_zone = *shorten_zone;  
999   if (NULL != zone)
1000   {
1001     shorten_msg->use_default_zone = htonl (GNUNET_NO);
1002     memcpy (&shorten_msg->zone, zone,
1003             sizeof (struct GNUNET_CRYPTO_ShortHashCode));
1004   }
1005   else
1006   {
1007     shorten_msg->use_default_zone = htonl (GNUNET_YES);
1008     memset (&shorten_msg->zone, 0, sizeof (struct GNUNET_CRYPTO_ShortHashCode));
1009   } 
1010   memcpy (&shorten_msg[1], name, strlen (name) + 1);
1011   GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail,
1012                                pending);  
1013   process_pending_messages (handle);
1014   return sr;
1015 }
1016
1017
1018 /**
1019  * Perform a name shortening operation on the GNS.
1020  *
1021  * @param handle handle to the GNS service
1022  * @param name the name to look up
1023  * @param private_zone the public zone of the private zone
1024  * @param shorten_zone the public zone of the shorten zone
1025  * @param proc function to call on result
1026  * @param proc_cls closure for processor
1027  * @return handle to the operation
1028  */
1029 struct GNUNET_GNS_ShortenRequest*
1030 GNUNET_GNS_shorten (struct GNUNET_GNS_Handle *handle,
1031                     const char *name,
1032                     struct GNUNET_CRYPTO_ShortHashCode *private_zone,
1033                     struct GNUNET_CRYPTO_ShortHashCode *shorten_zone,
1034                     GNUNET_GNS_ShortenResultProcessor proc,
1035                     void *proc_cls)
1036 {
1037   return GNUNET_GNS_shorten_zone (handle, name,
1038                                   private_zone, shorten_zone,
1039                                   NULL, proc, proc_cls);
1040 }
1041
1042
1043 /**
1044  * Perform an authority lookup for a given name.
1045  *
1046  * @param handle handle to the GNS service
1047  * @param name the name to look up authority for
1048  * @param proc function to call on result
1049  * @param proc_cls closure for processor
1050  * @return handle to the operation
1051  */
1052 struct GNUNET_GNS_GetAuthRequest*
1053 GNUNET_GNS_get_authority (struct GNUNET_GNS_Handle *handle,
1054                           const char *name,
1055                           GNUNET_GNS_GetAuthResultProcessor proc,
1056                           void *proc_cls)
1057 {
1058   struct GNUNET_GNS_ClientGetAuthMessage *get_auth_msg;
1059   struct GNUNET_GNS_GetAuthRequest *gar;
1060   size_t msize;
1061   struct PendingMessage *pending;
1062
1063   if (NULL == name)
1064   {
1065     GNUNET_break (0);
1066     return NULL;
1067   }
1068   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1069               "Trying to look up authority for %s in GNS\n", name);
1070   msize = sizeof (struct GNUNET_GNS_ClientGetAuthMessage) + strlen (name) + 1;
1071   if (msize > UINT16_MAX)
1072   {
1073     GNUNET_break (0);
1074     return NULL;
1075   }
1076   gar = GNUNET_malloc (sizeof (struct GNUNET_GNS_GetAuthRequest) +
1077                        sizeof (struct PendingMessage) + msize);
1078   gar->gns_handle = handle;
1079   gar->auth_proc = proc;
1080   gar->proc_cls = proc_cls;
1081   gar->r_id = handle->r_id_gen++;
1082   GNUNET_CONTAINER_DLL_insert_tail (handle->get_auth_head,
1083                                     handle->get_auth_tail, gar);
1084
1085   pending = (struct PendingMessage *) &gar[1];
1086   pending->size = msize;
1087   pending->r_id = gar->r_id;
1088   get_auth_msg = (struct GNUNET_GNS_ClientGetAuthMessage *) &pending[1];
1089   get_auth_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_GET_AUTH);
1090   get_auth_msg->header.size = htons (msize);
1091   get_auth_msg->id = htonl (gar->r_id);
1092   memcpy (&get_auth_msg[1], name, strlen (name) + 1);
1093   GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, 
1094                                     handle->pending_tail,
1095                                     pending);
1096   process_pending_messages (handle);
1097   return gar;
1098 }
1099
1100
1101 /* end of gns_api.c */