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