-simplify
[oweals/gnunet.git] / src / namestore / namestore_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010, 2011, 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 /**
22  * @file namestore/namestore_api.c
23  * @brief API to access the NAMESTORE service
24  * @author Martin Schanzenbach
25  * @author Matthias Wachs
26  * @author Christian Grothoff
27  */
28
29 #include "platform.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_crypto_lib.h"
32 #include "gnunet_constants.h"
33 #include "gnunet_dnsparser_lib.h"
34 #include "gnunet_arm_service.h"
35 #include "gnunet_signatures.h"
36 #include "gnunet_namestore_service.h"
37 #include "namestore.h"
38
39
40 #define LOG(kind,...) GNUNET_log_from (kind, "namestore-api",__VA_ARGS__)
41
42
43 /**
44  * An QueueEntry used to store information for a pending
45  * NAMESTORE record operation
46  */
47 struct GNUNET_NAMESTORE_QueueEntry
48 {
49
50   /**
51    * Kept in a DLL.
52    */
53   struct GNUNET_NAMESTORE_QueueEntry *next;
54
55   /**
56    * Kept in a DLL.
57    */
58   struct GNUNET_NAMESTORE_QueueEntry *prev;
59
60   /**
61    * Main handle to access the namestore.
62    */
63   struct GNUNET_NAMESTORE_Handle *nsh;
64
65   /**
66    * Continuation to call
67    */
68   GNUNET_NAMESTORE_ContinuationWithStatus cont;
69
70   /**
71    * Closure for 'cont'.
72    */
73   void *cont_cls;
74
75   /**
76    * Function to call with the records we get back; or NULL.
77    */
78   GNUNET_NAMESTORE_RecordProcessor proc;
79
80   /**
81    * Closure for 'proc'.
82    */
83   void *proc_cls;
84
85   /**
86    * The operation id this zone iteration operation has
87    */
88   uint32_t op_id;
89
90 };
91
92
93 /**
94  * Handle for a zone iterator operation
95  */
96 struct GNUNET_NAMESTORE_ZoneIterator
97 {
98
99   /**
100    * Kept in a DLL.
101    */
102   struct GNUNET_NAMESTORE_ZoneIterator *next;
103
104   /**
105    * Kept in a DLL.
106    */
107   struct GNUNET_NAMESTORE_ZoneIterator *prev;
108
109   /**
110    * Main handle to access the namestore.
111    */
112   struct GNUNET_NAMESTORE_Handle *h;
113
114   /**
115    * The continuation to call with the results
116    */
117   GNUNET_NAMESTORE_RecordProcessor proc;
118
119   /**
120    * Closure for 'proc'.
121    */
122   void* proc_cls;
123
124   /**
125    * If this iterator iterates over a specific zone this value contains the
126    * short hash of the zone
127    */
128   struct GNUNET_CRYPTO_ShortHashCode zone;
129
130   /**
131    * The operation id this zone iteration operation has
132    */
133   uint32_t op_id;
134
135   /**
136    * GNUNET_YES if this iterator iterates over a specific zone
137    * GNUNET_NO if this iterator iterates over all zones
138    *
139    * Zone is stored GNUNET_CRYPTO_ShortHashCode 'zone';
140    */
141   int has_zone;
142 };
143
144
145 /**
146  * Message in linked list we should send to the service.  The
147  * actual binary message follows this struct.
148  */
149 struct PendingMessage
150 {
151
152   /**
153    * Kept in a DLL.
154    */
155   struct PendingMessage *next;
156
157   /**
158    * Kept in a DLL.
159    */
160   struct PendingMessage *prev;
161
162   /**
163    * Size of the message.
164    */
165   size_t size;
166
167   /**
168    * Is this the 'START' message?
169    */
170   int is_init;
171 };
172
173
174 /**
175  * Connection to the NAMESTORE service.
176  */
177 struct GNUNET_NAMESTORE_Handle
178 {
179
180   /**
181    * Configuration to use.
182    */
183   const struct GNUNET_CONFIGURATION_Handle *cfg;
184
185   /**
186    * Socket (if available).
187    */
188   struct GNUNET_CLIENT_Connection *client;
189
190   /**
191    * Currently pending transmission request (or NULL).
192    */
193   struct GNUNET_CLIENT_TransmitHandle *th;
194
195   /**
196    * Head of linked list of pending messages to send to the service
197    */
198   struct PendingMessage * pending_head;
199
200   /**
201    * Tail of linked list of pending messages to send to the service
202    */
203   struct PendingMessage * pending_tail;
204
205   /**
206    * Head of pending namestore queue entries
207    */
208   struct GNUNET_NAMESTORE_QueueEntry * op_head;
209
210   /**
211    * Tail of pending namestore queue entries
212    */
213   struct GNUNET_NAMESTORE_QueueEntry * op_tail;
214
215   /**
216    * Head of pending namestore zone iterator entries
217    */
218   struct GNUNET_NAMESTORE_ZoneIterator * z_head;
219
220   /**
221    * Tail of pending namestore zone iterator entries
222    */
223   struct GNUNET_NAMESTORE_ZoneIterator * z_tail;
224
225   /**
226    * Reconnect task
227    */
228   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
229
230   /**
231    * Should we reconnect to service due to some serious error?
232    */
233   int reconnect;
234
235   /**
236    * The last operation id used for a NAMESTORE operation
237    */
238   uint32_t last_op_id_used;
239
240 };
241
242
243 /**
244  * Disconnect from service and then reconnect.
245  *
246  * @param h our handle
247  */
248 static void
249 force_reconnect (struct GNUNET_NAMESTORE_Handle *h);
250
251
252 /**
253  * Handle an incoming message of type 'GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE'
254  *
255  * @param qe the respective entry in the message queue
256  * @param msg the message we received
257  * @param size the message size
258  * @return GNUNET_OK on success, GNUNET_SYSERR on error and we did NOT notify the client
259  */
260 static int
261 handle_lookup_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
262                              const struct LookupNameResponseMessage * msg,
263                              size_t size)
264 {
265   const char *name;
266   const char * rd_tmp;
267   const struct GNUNET_CRYPTO_RsaSignature *signature;
268   struct GNUNET_TIME_Absolute expire;
269   const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key_tmp;
270   size_t exp_msg_len;
271   size_t msg_len;
272   size_t name_len;
273   size_t rd_len;
274   int contains_sig;
275   int rd_count;
276
277   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s'\n", "LOOKUP_NAME_RESPONSE");
278   rd_len = ntohs (msg->rd_len);
279   rd_count = ntohs (msg->rd_count);
280   msg_len = ntohs (msg->gns_header.header.size);
281   name_len = ntohs (msg->name_len);
282   contains_sig = ntohs (msg->contains_sig);
283   expire = GNUNET_TIME_absolute_ntoh (msg->expire);
284   exp_msg_len = sizeof (struct LookupNameResponseMessage) +
285       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
286       name_len + rd_len;
287   if (msg_len != exp_msg_len)
288   {
289     GNUNET_break (0);
290     return GNUNET_SYSERR;
291   }
292   name = (const char *) &msg[1];
293   if ( (name_len > 0) &&
294        ('\0' != name[name_len -1]) )
295   {
296     GNUNET_break (0);
297     return GNUNET_SYSERR;
298   }
299   rd_tmp = &name[name_len];
300   {
301     struct GNUNET_NAMESTORE_RecordData rd[rd_count];
302
303     if (GNUNET_OK != GNUNET_NAMESTORE_records_deserialize(rd_len, rd_tmp, rd_count, rd))
304     {
305       GNUNET_break (0);
306       return GNUNET_SYSERR;
307     }
308     if (GNUNET_NO == contains_sig)
309       signature = NULL;
310     else
311       signature = &msg->signature;
312     if (0 == name_len)
313       name = NULL;
314     if (NULL != name)
315       public_key_tmp = &msg->public_key;
316     else
317       public_key_tmp = NULL;    
318     if (NULL != qe->proc)
319       qe->proc (qe->proc_cls, public_key_tmp, expire, name, rd_count, (rd_count > 0) ? rd : NULL, signature);      
320   }
321   return GNUNET_OK;
322 }
323
324
325 /**
326  * Handle an incoming message of type 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE'
327  *
328  * @param qe the respective entry in the message queue
329  * @param msg the message we received
330  * @param size the message size
331  * @return GNUNET_OK on success, GNUNET_SYSERR on error and we did NOT notify the client
332  */
333 static int
334 handle_record_put_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
335                             const struct RecordPutResponseMessage* msg,
336                             size_t size)
337 {
338   int res;
339
340   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s'\n",
341        "RECORD_PUT_RESPONSE");
342   res = ntohl (msg->op_result);
343   /* TODO: add actual error message from namestore to response... */
344   if (NULL != qe->cont)    
345     qe->cont (qe->cont_cls, res, (GNUNET_OK == res) ? NULL : _("Namestore failed to add record"));
346   return GNUNET_OK;
347 }
348
349
350 /**
351  * Handle an incoming message of type 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE'
352  *
353  * @param qe the respective entry in the message queue
354  * @param msg the message we received
355  * @param size the message size
356  * @return GNUNET_OK on success, GNUNET_SYSERR on error and we did NOT notify the client
357  */
358 static int
359 handle_record_create_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
360                                const struct RecordCreateResponseMessage* msg,
361                                size_t size)
362 {
363   int res;
364   const char *emsg;
365   
366   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s'\n",
367        "RECORD_CREATE_RESPONSE");
368   /* TODO: add actual error message from namestore to response... */
369   res = ntohl (msg->op_result);
370   if (GNUNET_SYSERR == res)
371     emsg = _("Namestore failed to add record\n");
372   else
373     emsg = NULL;
374   if (NULL != qe->cont)    
375     qe->cont (qe->cont_cls, res, emsg);
376   return GNUNET_OK;
377 }
378
379
380 /**
381  * Handle an incoming message of type 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE'
382  *
383  * @param qe the respective entry in the message queue
384  * @param msg the message we received
385  * @param size the message size
386  * @return GNUNET_OK on success, GNUNET_SYSERR on error and we did NOT notify the client
387  */
388 static int
389 handle_record_remove_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
390                                const struct RecordRemoveResponseMessage* msg,
391                                size_t size)
392 {
393   int ret;
394   const char *emsg;
395
396   /* Operation done, remove */
397   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s'\n",
398        "RECORD_REMOVE_RESPONSE");
399   switch (ntohl (msg->op_result)) 
400   {
401   case RECORD_REMOVE_RESULT_SUCCESS:
402     ret = GNUNET_OK;
403     emsg = NULL;
404     break;
405   case RECORD_REMOVE_RESULT_NO_RECORDS:
406     ret = GNUNET_NO;
407     emsg = NULL;
408     break;
409   case RECORD_REMOVE_RESULT_RECORD_NOT_FOUND:
410     ret = GNUNET_NO;
411     emsg = NULL;
412     break;
413   case RECORD_REMOVE_RESULT_FAILED_TO_SIGN:
414     ret = GNUNET_SYSERR;
415     emsg = _("Failed to create new signature");
416     break;
417   case RECORD_REMOVE_RESULT_FAILED_TO_PUT_UPDATE:
418     ret = GNUNET_SYSERR;
419     emsg = _("Failed to put new set of records in database");
420     break;
421   case RECORD_REMOVE_RESULT_FAILED_TO_REMOVE:
422     ret = GNUNET_SYSERR;
423     emsg = _("Failed to remove records from database");
424     break;
425   case RECORD_REMOVE_RESULT_FAILED_ACCESS_DATABASE:
426     ret = GNUNET_SYSERR;
427     emsg = _("Failed to access database");
428     break;
429   case RECORD_REMOVE_RESULT_FAILED_INTERNAL_ERROR:
430     ret = GNUNET_SYSERR;
431     emsg = _("unknown internal error in namestore");
432     break;
433   default:
434     GNUNET_break (0);
435     if (NULL != qe->cont)      
436       qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Protocol error"));
437     return GNUNET_NO;
438   }
439   if (NULL != qe->cont)      
440     qe->cont (qe->cont_cls, ret, emsg);
441   return GNUNET_OK;
442 }
443
444
445 /**
446  * Handle an incoming message of type 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE'
447  *
448  * @param qe the respective entry in the message queue
449  * @param msg the message we received
450  * @param size the message size
451  * @return GNUNET_OK on success, GNUNET_NO if we notified the client about
452  *         the error, GNUNET_SYSERR on error and we did NOT notify the client
453  */
454 static int
455 handle_zone_to_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
456                               const struct ZoneToNameResponseMessage* msg,
457                               size_t size)
458 {
459   int res;
460   struct GNUNET_TIME_Absolute expire;
461   size_t name_len;
462   size_t rd_ser_len;
463   unsigned int rd_count;
464   const char * name_tmp;
465   const char * rd_tmp;
466
467   LOG (GNUNET_ERROR_TYPE_DEBUG, 
468        "Received `%s'\n",
469        "ZONE_TO_NAME_RESPONSE");
470   res = ntohs (msg->res);
471   switch (res)
472   {
473   case GNUNET_SYSERR:
474     LOG (GNUNET_ERROR_TYPE_DEBUG, "An error occured during zone to name operation\n");
475     break;
476   case GNUNET_NO:
477     LOG (GNUNET_ERROR_TYPE_DEBUG, "Namestore has no result for zone to name mapping \n");
478     break;
479   case GNUNET_YES:
480     LOG (GNUNET_ERROR_TYPE_DEBUG, "Namestore has result for zone to name mapping \n");
481     name_len = ntohs (msg->name_len);
482     rd_count = ntohs (msg->rd_count);
483     rd_ser_len = ntohs (msg->rd_len);
484     expire = GNUNET_TIME_absolute_ntoh(msg->expire);
485     name_tmp = (const char *) &msg[1];
486     if ( (name_len > 0) &&
487          ('\0' != name_tmp[name_len -1]) )
488     {
489       GNUNET_break (0);
490       return GNUNET_SYSERR;
491     }
492     rd_tmp = &name_tmp[name_len];
493     {
494       struct GNUNET_NAMESTORE_RecordData rd[rd_count];
495       if (GNUNET_OK != GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_tmp, rd_count, rd))
496       {
497         GNUNET_break (0);
498         return GNUNET_SYSERR;
499       }
500       /* normal end, call continuation with result */
501       if (NULL != qe->proc)
502         qe->proc (qe->proc_cls, &msg->zone_key, expire, name_tmp, rd_count, rd, &msg->signature);           
503       /* return is important here: break would call continuation with error! */
504       return GNUNET_OK;
505     }
506   default:
507     GNUNET_break (0);
508     return GNUNET_SYSERR;
509   }
510   /* error case, call continuation with error */
511   if (NULL != qe->proc)
512     qe->proc (qe->proc_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, NULL, 0, NULL, NULL);
513   return GNUNET_OK;
514 }
515
516
517 /**
518  * Handle incoming messages for record operations
519  *
520  * @param qe the respective zone iteration handle
521  * @param msg the message we received
522  * @param type the message type in HBO
523  * @param size the message size
524  * @return GNUNET_OK on success, GNUNET_NO if we notified the client about
525  *         the error, GNUNET_SYSERR on error and we did NOT notify the client
526  */
527 static int
528 manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe,
529                           const struct GNUNET_MessageHeader *msg,
530                           uint16_t type, 
531                           size_t size)
532 {
533   /* handle different message type */
534   switch (type) 
535   {
536   case GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE:
537     if (size < sizeof (struct LookupNameResponseMessage))
538     {
539       GNUNET_break (0);
540       return GNUNET_SYSERR;
541     }
542     return handle_lookup_name_response (qe, (const struct LookupNameResponseMessage *) msg, size);
543   case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE:
544     if (size != sizeof (struct RecordPutResponseMessage))
545     {
546       GNUNET_break (0);
547       return GNUNET_SYSERR;
548     }
549     return handle_record_put_response (qe, (const struct RecordPutResponseMessage *) msg, size);
550   case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE:
551     if (size != sizeof (struct RecordCreateResponseMessage))
552     {
553       GNUNET_break (0);
554       return GNUNET_SYSERR;
555     }
556     return handle_record_create_response (qe, (const struct RecordCreateResponseMessage *) msg, size);
557   case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE:
558     if (size != sizeof (struct RecordRemoveResponseMessage))
559     {
560       GNUNET_break (0);
561       return GNUNET_SYSERR;
562     }
563     return handle_record_remove_response (qe, (const struct RecordRemoveResponseMessage *) msg, size);
564   case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE:
565     if (size < sizeof (struct ZoneToNameResponseMessage))
566     {
567       GNUNET_break (0);
568       return GNUNET_SYSERR;
569     }
570     return handle_zone_to_name_response (qe, (const struct ZoneToNameResponseMessage *) msg, size);
571   default:
572     GNUNET_break (0);
573     return GNUNET_SYSERR;
574   }
575 }
576
577
578 /**
579  * Handle a response from NAMESTORE service for a zone iteration request
580  *
581  * @param ze the respective iterator for this operation
582  * @param msg the message containing the respoonse
583  * @param size the message size
584  * @return GNUNET_YES on success, 'ze' should be kept, GNUNET_NO on success if 'ze' should
585  *         not be kept any longer, GNUNET_SYSERR on error (disconnect) and 'ze' should be kept
586  */
587 static int
588 handle_zone_iteration_response (struct GNUNET_NAMESTORE_ZoneIterator *ze,
589                                 const struct ZoneIterationResponseMessage *msg,
590                                 size_t size)
591 {
592   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubdummy;
593   size_t msg_len;
594   size_t exp_msg_len;
595   size_t name_len;
596   size_t rd_len;
597   unsigned rd_count;
598   const char *name_tmp;
599   const char *rd_ser_tmp;
600   struct GNUNET_TIME_Absolute expire;
601
602   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s'\n",
603        "ZONE_ITERATION_RESPONSE");
604   msg_len = ntohs (msg->gns_header.header.size);
605   rd_len = ntohs (msg->rd_len);
606   rd_count = ntohs (msg->rd_count);
607   name_len = ntohs (msg->name_len);
608   expire = GNUNET_TIME_absolute_ntoh (msg->expire);
609   exp_msg_len = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_len;
610   if (msg_len != exp_msg_len)
611   {
612     GNUNET_break (0);
613     return GNUNET_SYSERR;
614   }
615   GNUNET_break (0 == ntohs (msg->reserved));
616   memset (&pubdummy, '\0', sizeof (pubdummy));
617   if ((0 == name_len) && (0 == (memcmp (&msg->public_key, &pubdummy, sizeof (pubdummy)))))
618   {
619     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration is completed!\n");
620     if (NULL != ze->proc)
621       ze->proc(ze->proc_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, NULL , 0, NULL, NULL);
622     return GNUNET_NO;
623   }
624   name_tmp = (const char *) &msg[1];
625   if ((name_tmp[name_len -1] != '\0') || (name_len > MAX_NAME_LEN))
626   {
627     GNUNET_break (0);
628     return GNUNET_SYSERR;
629   }
630   rd_ser_tmp = (const char *) &name_tmp[name_len];
631   {
632     struct GNUNET_NAMESTORE_RecordData rd[rd_count];
633
634     if (GNUNET_OK != GNUNET_NAMESTORE_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd))
635     {
636       GNUNET_break (0);
637       return GNUNET_SYSERR;
638     }
639     if (NULL != ze->proc)
640       ze->proc(ze->proc_cls, &msg->public_key, expire, name_tmp, rd_count, rd, &msg->signature);
641     return GNUNET_YES;
642   }
643 }
644
645
646 /**
647  * Handle incoming messages for zone iterations
648  *
649  * @param ze the respective zone iteration handle
650  * @param msg the message we received
651  * @param type the message type in HBO
652  * @param size the message size
653  * @return GNUNET_YES on success, 'ze' should be kept, GNUNET_NO on success if 'ze' should
654  *         not be kept any longer, GNUNET_SYSERR on error (disconnect) and 'ze' should be kept
655  */
656 static int
657 manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze,
658                         const struct GNUNET_MessageHeader *msg,
659                         int type, size_t size)
660 {
661   /* handle different message type */
662   switch (type) 
663   {
664   case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE:
665     if (size < sizeof (struct ZoneIterationResponseMessage))
666     {
667       GNUNET_break (0);
668       return GNUNET_SYSERR;
669     }
670     return handle_zone_iteration_response (ze, (const struct ZoneIterationResponseMessage *) msg, size);
671   default:
672     GNUNET_break (0);
673     return GNUNET_SYSERR;
674   }
675 }
676
677
678 /**
679  * Type of a function to call when we receive a message
680  * from the service.
681  *
682  * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle'
683  * @param msg message received, NULL on timeout or fatal error
684  */
685 static void
686 process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg)
687 {
688   struct GNUNET_NAMESTORE_Handle *h = cls;
689   const struct GNUNET_NAMESTORE_Header *gm;
690   struct GNUNET_NAMESTORE_QueueEntry *qe;
691   struct GNUNET_NAMESTORE_ZoneIterator *ze;
692   uint16_t size;
693   uint16_t type;
694   uint32_t r_id;
695   int ret;
696
697   if (NULL == msg)
698   {
699     force_reconnect (h);
700     return;
701   }
702   size = ntohs (msg->size);
703   type = ntohs (msg->type);
704   if (size < sizeof (struct GNUNET_NAMESTORE_Header))
705   {
706     GNUNET_break_op (0);
707     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
708                            GNUNET_TIME_UNIT_FOREVER_REL);
709     return;
710   }
711   gm = (const struct GNUNET_NAMESTORE_Header *) msg;
712   r_id = ntohl (gm->r_id);
713
714   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message type %u size %u op %u\n", 
715        (unsigned int) type,
716        (unsigned int) size, 
717        (unsigned int) r_id);
718
719   /* Is it a record related operation ? */
720   for (qe = h->op_head; qe != NULL; qe = qe->next)
721     if (qe->op_id == r_id)
722       break;
723   if (NULL != qe)
724   {
725     ret = manage_record_operations (qe, msg, type, size);
726     if (GNUNET_OK != ret)    
727     {
728       /* protocol error, need to reconnect */
729       h->reconnect = GNUNET_YES;
730     }
731     if (GNUNET_SYSERR != ret)
732     {
733       /* client was notified about success or failure, clean up 'qe' */
734       GNUNET_CONTAINER_DLL_remove (h->op_head,
735                                    h->op_tail,
736                                    qe);
737       GNUNET_free (qe);
738     }
739   }
740
741   /* Is it a zone iteration operation ? */
742   for (ze = h->z_head; ze != NULL; ze = ze->next)
743     if (ze->op_id == r_id)
744       break;
745   if (NULL != ze)
746   {
747     ret = manage_zone_operations (ze, msg, type, size);
748     if (GNUNET_NO == ret)
749     {
750       /* end of iteration, clean up 'ze' */
751       GNUNET_CONTAINER_DLL_remove (h->z_head,
752                                    h->z_tail,
753                                    ze);
754       GNUNET_free (ze);
755     }
756     if (GNUNET_SYSERR == ret)
757     {
758       /* protocol error, need to reconnect */
759       h->reconnect = GNUNET_YES;
760     }
761   }
762   if (GNUNET_YES == h->reconnect)
763   {
764     force_reconnect (h);
765     return;
766   }
767   GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
768                          GNUNET_TIME_UNIT_FOREVER_REL);
769 }
770
771
772 /**
773  * Transmit messages from the message queue to the service
774  * (if there are any, and if we are not already trying).
775  *
776  * @param h handle to use
777  */
778 static void
779 do_transmit (struct GNUNET_NAMESTORE_Handle *h);
780
781
782 /**
783  * We can now transmit a message to NAMESTORE. Do it.
784  *
785  * @param cls the 'struct GNUNET_NAMESTORE_Handle'
786  * @param size number of bytes we can transmit
787  * @param buf where to copy the messages
788  * @return number of bytes copied into buf
789  */
790 static size_t
791 transmit_message_to_namestore (void *cls, size_t size, void *buf)
792 {
793   struct GNUNET_NAMESTORE_Handle *h = cls;
794   struct PendingMessage *p;
795   size_t ret;
796   char *cbuf;
797
798   h->th = NULL;
799   if ((0 == size) || (NULL == buf))
800   {
801     force_reconnect (h);
802     return 0;
803   }
804   ret = 0;
805   cbuf = buf;
806   while ((NULL != (p = h->pending_head)) && (p->size <= size))
807   {
808     memcpy (&cbuf[ret], &p[1], p->size);
809     ret += p->size;
810     size -= p->size;
811     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
812     if (GNUNET_YES == p->is_init)
813       GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
814                              GNUNET_TIME_UNIT_FOREVER_REL);
815     GNUNET_free (p);
816   }
817   do_transmit (h);
818   return ret;
819 }
820
821
822 /**
823  * Transmit messages from the message queue to the service
824  * (if there are any, and if we are not already trying).
825  *
826  * @param h handle to use
827  */
828 static void
829 do_transmit (struct GNUNET_NAMESTORE_Handle *h)
830 {
831   struct PendingMessage *p;
832
833   if (NULL != h->th)
834     return; /* transmission request already pending */
835   if (NULL == (p = h->pending_head))
836     return; /* transmission queue empty */
837   if (NULL == h->client)
838     return;                     /* currently reconnecting */
839   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size,
840                                            GNUNET_TIME_UNIT_FOREVER_REL,
841                                            GNUNET_NO, &transmit_message_to_namestore,
842                                            h);
843 }
844
845
846 /**
847  * Reconnect to namestore service.
848  *
849  * @param h the handle to the NAMESTORE service
850  */
851 static void
852 reconnect (struct GNUNET_NAMESTORE_Handle *h)
853 {
854   struct PendingMessage *p;
855   struct StartMessage *init;
856
857   GNUNET_assert (NULL == h->client);
858   h->client = GNUNET_CLIENT_connect ("namestore", h->cfg);
859   GNUNET_assert (NULL != h->client);
860   if ((NULL == (p = h->pending_head)) || (GNUNET_YES != p->is_init))
861   {
862     p = GNUNET_malloc (sizeof (struct PendingMessage) +
863                        sizeof (struct StartMessage));
864     p->size = sizeof (struct StartMessage);
865     p->is_init = GNUNET_YES;
866     init = (struct StartMessage *) &p[1];
867     init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START);
868     init->header.size = htons (sizeof (struct StartMessage));
869     GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, p);
870   }
871   do_transmit (h);
872 }
873
874
875 /**
876  * Re-establish the connection to the service.
877  *
878  * @param cls handle to use to re-connect.
879  * @param tc scheduler context
880  */
881 static void
882 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
883 {
884   struct GNUNET_NAMESTORE_Handle *h = cls;
885
886   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
887   reconnect (h);
888 }
889
890
891 /**
892  * Disconnect from service and then reconnect.
893  *
894  * @param h our handle
895  */
896 static void
897 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
898 {
899   h->reconnect = GNUNET_NO;
900   GNUNET_CLIENT_disconnect (h->client);
901   h->client = NULL;
902   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
903                                                     &reconnect_task,
904                                                     h);
905 }
906
907
908 /**
909  * Get a fresh operation id to distinguish between namestore requests
910  *
911  * @param h the namestore handle
912  * @return next operation id to use
913  */
914 static uint32_t
915 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
916 {
917   return h->last_op_id_used++;
918 }
919
920
921 /**
922  * Initialize the connection with the NAMESTORE service.
923  *
924  * @param cfg configuration to use
925  * @return handle to the GNS service, or NULL on error
926  */
927 struct GNUNET_NAMESTORE_Handle *
928 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
929 {
930   struct GNUNET_NAMESTORE_Handle *h;
931
932   h = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle));
933   h->cfg = cfg;
934   h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h);
935   h->last_op_id_used = 0;
936   return h;
937 }
938
939
940 /**
941  * Disconnect from the namestore service (and free associated
942  * resources).
943  *
944  * @param h handle to the namestore
945  */
946 void
947 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h)
948 {
949   struct PendingMessage *p;
950   struct GNUNET_NAMESTORE_QueueEntry *q;
951   struct GNUNET_NAMESTORE_ZoneIterator *z;
952
953   LOG (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
954   GNUNET_assert (NULL != h);
955   while (NULL != (p = h->pending_head))
956   {
957     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
958     GNUNET_free (p);
959   }
960   GNUNET_break (NULL == h->op_head);
961   while (NULL != (q = h->op_head))
962   {
963     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
964     GNUNET_free (q);
965   }
966   GNUNET_break (NULL == h->z_head);
967   while (NULL != (z = h->z_head))
968   {
969     GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
970     GNUNET_free (z);
971   }
972   if (NULL != h->client)
973   {
974     GNUNET_CLIENT_disconnect (h->client);
975     h->client = NULL;
976   }
977   if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task)
978   {
979     GNUNET_SCHEDULER_cancel (h->reconnect_task);
980     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
981   }
982   GNUNET_free (h);
983 }
984
985
986 /**
987  * Store an item in the namestore.  If the item is already present,
988  * the expiration time is updated to the max of the existing time and
989  * the new time.  This API is used when we cache signatures from other
990  * authorities.
991  *
992  * @param h handle to the namestore
993  * @param zone_key public key of the zone
994  * @param name name that is being mapped (at most 255 characters long)
995  * @param freshness when does the corresponding block in the DHT expire (until
996  *               when should we never do a DHT lookup for the same name again)?
997  * @param rd_count number of entries in 'rd' array
998  * @param rd array of records with data to store
999  * @param signature signature for all the records in the zone under the given name
1000  * @param cont continuation to call when done
1001  * @param cont_cls closure for cont
1002  * @return handle to abort the request
1003  */
1004 struct GNUNET_NAMESTORE_QueueEntry *
1005 GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
1006                              const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1007                              const char *name,
1008                              struct GNUNET_TIME_Absolute freshness,
1009                              unsigned int rd_count,
1010                              const struct GNUNET_NAMESTORE_RecordData *rd,
1011                              const struct GNUNET_CRYPTO_RsaSignature *signature,
1012                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
1013                              void *cont_cls)
1014 {
1015   struct GNUNET_NAMESTORE_QueueEntry *qe;
1016   struct PendingMessage *pe;
1017   struct RecordPutMessage * msg;
1018   char * rd_ser;
1019   char * name_tmp;
1020   size_t msg_size;
1021   size_t name_len;
1022   size_t rd_ser_len;
1023   uint32_t rid;
1024
1025   GNUNET_assert (NULL != h);
1026   GNUNET_assert (NULL != zone_key);
1027   GNUNET_assert (NULL != name);
1028   GNUNET_assert (NULL != rd);
1029   GNUNET_assert (NULL != signature);
1030   LOG (GNUNET_ERROR_TYPE_DEBUG,
1031        "Storing %u records under name `%s'\n",
1032        rd_count,
1033        name);
1034   name_len = strlen(name) + 1;
1035   if (name_len > MAX_NAME_LEN)
1036   {
1037     GNUNET_break (0);
1038     return NULL;
1039   }
1040   rid = get_op_id (h);
1041   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1042   qe->nsh = h;
1043   qe->cont = cont;
1044   qe->cont_cls = cont_cls;
1045   qe->op_id = rid;
1046   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1047
1048   /* setup msg */
1049   rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
1050   msg_size = sizeof (struct RecordPutMessage) + name_len  + rd_ser_len;
1051   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1052   pe->size = msg_size;
1053   pe->is_init = GNUNET_NO;
1054   msg = (struct RecordPutMessage *) &pe[1];
1055   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
1056   msg->gns_header.header.size = htons (msg_size);
1057   msg->gns_header.r_id = htonl (rid);
1058   msg->signature = *signature;
1059   msg->name_len = htons (name_len);
1060   msg->expire = GNUNET_TIME_absolute_hton (freshness);
1061   msg->rd_len = htons (rd_ser_len);
1062   msg->rd_count = htons (rd_count);
1063   msg->public_key = *zone_key;
1064   name_tmp = (char *) &msg[1];
1065   memcpy (name_tmp, name, name_len);
1066   rd_ser = &name_tmp[name_len];
1067   GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1068   LOG (GNUNET_ERROR_TYPE_DEBUG, 
1069        "Sending `%s' message for name `%s' with size %u\n", 
1070        "NAMESTORE_RECORD_PUT", 
1071        name, msg_size);
1072   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1073   do_transmit(h);
1074   return qe;
1075 }
1076
1077
1078 /**
1079  * Check if a signature is valid.  This API is used by the GNS Block
1080  * to validate signatures received from the network.
1081  *
1082  * @param public_key public key of the zone
1083  * @param freshness block expiration
1084  * @param name name that is being mapped (at most 255 characters long)
1085  * @param rd_count number of entries in 'rd' array
1086  * @param rd array of records with data to store
1087  * @param signature signature for all the records in the zone under the given name
1088  * @return GNUNET_OK if the signature is valid
1089  */
1090 int
1091 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
1092                                    const struct GNUNET_TIME_Absolute freshness,
1093                                    const char *name,
1094                                    unsigned int rd_count,
1095                                    const struct GNUNET_NAMESTORE_RecordData *rd,
1096                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
1097 {
1098   size_t rd_ser_len;
1099   size_t name_len;
1100   char *name_tmp;
1101   char *rd_ser;
1102   struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose;
1103   struct GNUNET_TIME_AbsoluteNBO *expire_tmp;
1104   struct GNUNET_TIME_AbsoluteNBO expire_nbo = GNUNET_TIME_absolute_hton (freshness);
1105   uint32_t sig_len;
1106
1107   GNUNET_assert (NULL != public_key);
1108   GNUNET_assert (NULL != name);
1109   GNUNET_assert (NULL != rd);
1110   GNUNET_assert (NULL != signature);
1111   name_len = strlen (name) + 1;
1112   if (name_len > MAX_NAME_LEN)
1113   {
1114     GNUNET_break (0);
1115     return GNUNET_SYSERR;
1116   }
1117   rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1118   sig_len = sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + rd_ser_len + name_len;
1119   {
1120     char sig_buf[sig_len] GNUNET_ALIGN;
1121
1122     sig_purpose = (struct GNUNET_CRYPTO_RsaSignaturePurpose *) sig_buf;
1123     sig_purpose->size = htonl (sig_len);
1124     sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
1125     expire_tmp = (struct GNUNET_TIME_AbsoluteNBO *) &sig_purpose[1];
1126     memcpy (expire_tmp, &expire_nbo, sizeof (struct GNUNET_TIME_AbsoluteNBO));
1127     name_tmp = (char *) &expire_tmp[1];
1128     memcpy (name_tmp, name, name_len);
1129     rd_ser = &name_tmp[name_len];
1130     GNUNET_assert (rd_ser_len ==
1131                    GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_ser));
1132     return GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, sig_purpose, signature, public_key);
1133   }
1134 }
1135
1136
1137 /**
1138  * Store an item in the namestore.  If the item is already present,
1139  * the expiration time is updated to the max of the existing time and
1140  * the new time.  This API is used by the authority of a zone.
1141  *
1142  * @param h handle to the namestore
1143  * @param pkey private key of the zone
1144  * @param name name that is being mapped (at most 255 characters long)
1145  * @param rd record data to store
1146  * @param cont continuation to call when done
1147  * @param cont_cls closure for cont
1148  * @return handle to abort the request
1149  */
1150 struct GNUNET_NAMESTORE_QueueEntry *
1151 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
1152                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1153                                 const char *name,
1154                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1155                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1156                                 void *cont_cls)
1157 {
1158   struct GNUNET_NAMESTORE_QueueEntry *qe;
1159   struct PendingMessage *pe;
1160   char * name_tmp;
1161   char * pkey_tmp;
1162   char * rd_ser;
1163   size_t rd_ser_len;
1164   size_t msg_size;
1165   size_t name_len;
1166   size_t key_len;
1167   uint32_t rid;
1168   struct RecordCreateMessage * msg;
1169   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc;
1170
1171   GNUNET_assert (NULL != h);
1172   GNUNET_assert (NULL != pkey);
1173   GNUNET_assert (NULL != name);
1174   GNUNET_assert (NULL != rd);
1175   LOG (GNUNET_ERROR_TYPE_DEBUG,
1176        "Creating record of type %u under name `%s'\n",
1177        rd->record_type,
1178        name);
1179   name_len = strlen(name) + 1;
1180   if (name_len > MAX_NAME_LEN)
1181   {
1182     GNUNET_break (0);
1183     return NULL;
1184   }
1185   rid = get_op_id(h);
1186   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1187   qe->nsh = h;
1188   qe->cont = cont;
1189   qe->cont_cls = cont_cls;
1190   qe->op_id = rid;
1191   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1192
1193   pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1194   GNUNET_assert (NULL != pkey_enc);
1195
1196   /* setup msg */
1197   key_len = ntohs (pkey_enc->len);
1198   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1199   msg_size = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1200   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1201   pe->size = msg_size;
1202   pe->is_init = GNUNET_NO;
1203   msg = (struct RecordCreateMessage *) &pe[1];
1204   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
1205   msg->gns_header.header.size = htons (msg_size);
1206   msg->gns_header.r_id = htonl (rid);
1207   msg->name_len = htons (name_len);
1208   msg->rd_count = htons (1);
1209   msg->rd_len = htons (rd_ser_len);
1210   msg->pkey_len = htons (key_len);
1211   msg->expire = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_FOREVER_ABS);
1212   pkey_tmp = (char *) &msg[1];
1213   memcpy (pkey_tmp, pkey_enc, key_len);
1214   name_tmp = &pkey_tmp[key_len];
1215   memcpy (name_tmp, name, name_len);
1216   rd_ser = &name_tmp[name_len];
1217   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1218
1219   GNUNET_free (pkey_enc);
1220
1221   LOG (GNUNET_ERROR_TYPE_DEBUG, 
1222        "Sending `%s' message for name `%s' with size %u\n", 
1223        "NAMESTORE_RECORD_CREATE", name, msg_size);
1224   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1225   do_transmit(h);
1226   return qe;
1227 }
1228
1229
1230 /**
1231  * Explicitly remove some content from the database.  The
1232  * "cont"inuation will be called with status "GNUNET_OK" if content
1233  * was removed, "GNUNET_NO" if no matching entry was found and
1234  * "GNUNET_SYSERR" on all other types of errors.
1235  * This API is used by the authority of a zone.
1236  *
1237  * @param h handle to the namestore
1238  * @param pkey private key of the zone
1239  * @param name name that is being mapped (at most 255 characters long)
1240  * @param rd record data, remove specific record,  NULL to remove the name and all records
1241  * @param cont continuation to call when done
1242  * @param cont_cls closure for cont
1243  * @return handle to abort the request
1244  */
1245 struct GNUNET_NAMESTORE_QueueEntry *
1246 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
1247                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1248                                 const char *name,
1249                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1250                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1251                                 void *cont_cls)
1252 {
1253   struct GNUNET_NAMESTORE_QueueEntry *qe;
1254   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc;
1255   struct PendingMessage *pe;
1256   struct RecordRemoveMessage * msg;
1257   char *pkey_tmp;
1258   char *rd_ser;
1259   char *name_tmp;
1260   size_t rd_ser_len;
1261   size_t msg_size;
1262   size_t name_len;
1263   size_t key_len;
1264   uint32_t rid;
1265   uint16_t rd_count;
1266
1267   GNUNET_assert (NULL != h);
1268   if (NULL != rd)
1269     LOG (GNUNET_ERROR_TYPE_DEBUG,
1270          "Removing record of type %u under name `%s'\n",
1271          rd->record_type,
1272          name);
1273   else
1274     LOG (GNUNET_ERROR_TYPE_DEBUG,
1275          "Removing all records under name `%s'\n",
1276          name);
1277   rid = get_op_id(h);
1278   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1279   qe->nsh = h;
1280   qe->cont = cont;
1281   qe->cont_cls = cont_cls;
1282   qe->op_id = rid;
1283   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1284
1285   pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1286   GNUNET_assert (NULL != pkey_enc);
1287   key_len = ntohs (pkey_enc->len);
1288
1289   rd_count = (NULL == rd) ? 0 : 1;
1290   rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1291   name_len = strlen (name) + 1;
1292   msg_size = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1293   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1294   pe->size = msg_size;
1295   pe->is_init = GNUNET_NO;
1296   msg = (struct RecordRemoveMessage *) &pe[1];
1297   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE);
1298   msg->gns_header.header.size = htons (msg_size);
1299   msg->gns_header.r_id = htonl (rid);
1300   msg->name_len = htons (name_len);
1301   msg->rd_len = htons (rd_ser_len);
1302   msg->rd_count = htons (rd_count);
1303   msg->pkey_len = htons (key_len);
1304   pkey_tmp = (char *) &msg[1];
1305   memcpy (pkey_tmp, pkey_enc, key_len);
1306   name_tmp = &pkey_tmp[key_len];
1307   memcpy (name_tmp, name, name_len);
1308   rd_ser = &name_tmp[name_len];
1309   GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_ser);
1310
1311   GNUNET_free (pkey_enc);
1312
1313   LOG (GNUNET_ERROR_TYPE_DEBUG, 
1314        "Sending `%s' message for name `%s' with size %u\n", 
1315        "NAMESTORE_RECORD_REMOVE", name, msg_size);
1316   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1317   do_transmit(h);
1318   return qe;
1319 }
1320
1321
1322 /**
1323  * Get a result for a particular key from the namestore.  The processor
1324  * will only be called once.  
1325  *
1326  * @param h handle to the namestore
1327  * @param zone zone to look up a record from
1328  * @param name name to look up
1329  * @param record_type desired record type, 0 for all
1330  * @param proc function to call on the matching records, or with
1331  *        NULL (rd_count == 0) if there are no matching records
1332  * @param proc_cls closure for proc
1333  * @return a handle that can be used to
1334  *         cancel
1335  */
1336 struct GNUNET_NAMESTORE_QueueEntry *
1337 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
1338                               const struct GNUNET_CRYPTO_ShortHashCode *zone,
1339                               const char *name,
1340                               uint32_t record_type,
1341                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
1342 {
1343   struct GNUNET_NAMESTORE_QueueEntry *qe;
1344   struct PendingMessage *pe;
1345   struct LookupNameMessage * msg;
1346   size_t msg_size;
1347   size_t name_len;
1348   uint32_t rid;
1349
1350   GNUNET_assert (NULL != h);
1351   GNUNET_assert (NULL != zone);
1352   GNUNET_assert (NULL != name);
1353   LOG (GNUNET_ERROR_TYPE_DEBUG,
1354        "Looking for record of type %u under name `%s'\n",
1355        record_type,
1356        name);
1357   name_len = strlen (name) + 1;
1358   if ((name_len == 0) || (name_len > MAX_NAME_LEN))
1359   {
1360     GNUNET_break (0);
1361     return NULL;
1362   }
1363
1364   rid = get_op_id(h);
1365   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1366   qe->nsh = h;
1367   qe->proc = proc;
1368   qe->proc_cls = proc_cls;
1369   qe->op_id = rid;
1370   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1371
1372   msg_size = sizeof (struct LookupNameMessage) + name_len;
1373   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1374   pe->size = msg_size;
1375   pe->is_init = GNUNET_NO;
1376   msg = (struct LookupNameMessage *) &pe[1];
1377   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
1378   msg->gns_header.header.size = htons (msg_size);
1379   msg->gns_header.r_id = htonl (rid);
1380   msg->record_type = htonl (record_type);
1381   msg->name_len = htonl (name_len);
1382   msg->zone = *zone;
1383   memcpy (&msg[1], name, name_len);
1384
1385   LOG (GNUNET_ERROR_TYPE_DEBUG,
1386        "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
1387   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1388   do_transmit(h);
1389   return qe;
1390 }
1391
1392
1393 /**
1394  * Look for an existing PKEY delegation record for a given public key.
1395  * Returns at most one result to the processor.
1396  *
1397  * @param h handle to the namestore
1398  * @param zone hash of public key of the zone to look up in, never NULL
1399  * @param value_zone hash of the public key of the target zone (value), never NULL
1400  * @param proc function to call on the matching records, or with
1401  *        NULL (rd_count == 0) if there are no matching records
1402  * @param proc_cls closure for proc
1403  * @return a handle that can be used to
1404  *         cancel
1405  */
1406 struct GNUNET_NAMESTORE_QueueEntry *
1407 GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h,
1408                                const struct GNUNET_CRYPTO_ShortHashCode *zone,
1409                                const struct GNUNET_CRYPTO_ShortHashCode *value_zone,
1410                                GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
1411 {
1412   struct GNUNET_NAMESTORE_QueueEntry *qe;
1413   struct PendingMessage *pe;
1414   struct ZoneToNameMessage * msg;
1415   size_t msg_size;
1416   uint32_t rid;
1417
1418   GNUNET_assert (NULL != h);
1419   GNUNET_assert (NULL != zone);
1420   GNUNET_assert (NULL != value_zone);
1421   rid = get_op_id(h);
1422   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1423   qe->nsh = h;
1424   qe->proc = proc;
1425   qe->proc_cls = proc_cls;
1426   qe->op_id = rid;
1427   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1428
1429   msg_size = sizeof (struct ZoneToNameMessage);
1430   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1431   pe->size = msg_size;
1432   pe->is_init = GNUNET_NO;
1433   msg = (struct ZoneToNameMessage *) &pe[1];
1434   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1435   msg->gns_header.header.size = htons (msg_size);
1436   msg->gns_header.r_id = htonl (rid);
1437   msg->zone = *zone;
1438   msg->value_zone = *value_zone;
1439
1440   /* transmit message */
1441   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1442   do_transmit(h);
1443   return qe;
1444 }
1445
1446
1447 /**
1448  * Starts a new zone iteration (used to periodically PUT all of our
1449  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
1450  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
1451  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
1452  * immediately, and then again after
1453  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
1454  *
1455  * @param h handle to the namestore
1456  * @param zone zone to access, NULL for all zones
1457  * @param must_have_flags flags that must be set for the record to be returned
1458  * @param must_not_have_flags flags that must NOT be set for the record to be returned
1459  * @param proc function to call on each name from the zone; it
1460  *        will be called repeatedly with a value (if available)
1461  *        and always once at the end with a name of NULL.
1462  * @param proc_cls closure for proc
1463  * @return an iterator handle to use for iteration
1464  */
1465 struct GNUNET_NAMESTORE_ZoneIterator *
1466 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1467                                        const struct GNUNET_CRYPTO_ShortHashCode *zone,
1468                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
1469                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
1470                                        GNUNET_NAMESTORE_RecordProcessor proc,
1471                                        void *proc_cls)
1472 {
1473   struct GNUNET_NAMESTORE_ZoneIterator *it;
1474   struct PendingMessage *pe;
1475   struct ZoneIterationStartMessage * msg;
1476   size_t msg_size;
1477   uint32_t rid;
1478
1479   GNUNET_assert (NULL != h);
1480   rid = get_op_id(h);
1481   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
1482   it->h = h;
1483   it->proc = proc;
1484   it->proc_cls = proc_cls;
1485   it->op_id = rid;
1486   if (NULL != zone)
1487   {
1488     it->zone = *zone;
1489     it->has_zone = GNUNET_YES;
1490   }
1491   else
1492   {
1493     memset (&it->zone, '\0', sizeof (it->zone));
1494     it->has_zone = GNUNET_NO;
1495   }
1496   GNUNET_CONTAINER_DLL_insert_tail (h->z_head, h->z_tail, it);
1497
1498   msg_size = sizeof (struct ZoneIterationStartMessage);
1499   pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size);
1500   pe->size = msg_size;
1501   pe->is_init = GNUNET_NO;
1502   msg = (struct ZoneIterationStartMessage *) &pe[1];
1503   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1504   msg->gns_header.header.size = htons (msg_size);
1505   msg->gns_header.r_id = htonl (rid);
1506   if (NULL != zone)
1507   {
1508     LOG (GNUNET_ERROR_TYPE_DEBUG, 
1509          "Sending `%s' message for zone `%s'\n", 
1510          "ZONE_ITERATION_START", GNUNET_short_h2s(zone));
1511     msg->zone = *zone;
1512   }
1513   else
1514   {
1515     LOG (GNUNET_ERROR_TYPE_DEBUG, 
1516          "Sending `%s' message for all zones\n", "ZONE_ITERATION_START");
1517     memset (&msg->zone, '\0', sizeof (msg->zone));
1518   }
1519   msg->must_have_flags = ntohs (must_have_flags);
1520   msg->must_not_have_flags = ntohs (must_not_have_flags);
1521   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1522   do_transmit(h);
1523   return it;
1524 }
1525
1526
1527 /**
1528  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
1529  * for the next record.
1530  *
1531  * @param it the iterator
1532  */
1533 void
1534 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1535 {
1536   struct GNUNET_NAMESTORE_Handle *h;
1537   struct ZoneIterationNextMessage * msg;
1538   struct PendingMessage *pe;
1539   size_t msg_size;
1540
1541   GNUNET_assert (NULL != it);
1542   h = it->h;
1543   msg_size = sizeof (struct ZoneIterationNextMessage);
1544   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1545   pe->size = msg_size;
1546   pe->is_init = GNUNET_NO;
1547   msg = (struct ZoneIterationNextMessage *) &pe[1];
1548   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1549   msg->gns_header.header.size = htons (msg_size);
1550   msg->gns_header.r_id = htonl (it->op_id);
1551   LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_NEXT");
1552   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1553   do_transmit(h);
1554 }
1555
1556
1557 /**
1558  * Stops iteration and releases the namestore handle for further calls.
1559  *
1560  * @param it the iterator
1561  */
1562 void
1563 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1564 {
1565   struct GNUNET_NAMESTORE_Handle *h;
1566   struct PendingMessage *pe;
1567   size_t msg_size;
1568   struct ZoneIterationStopMessage * msg;
1569
1570   GNUNET_assert (NULL != it);
1571   h = it->h;
1572   GNUNET_CONTAINER_DLL_remove (h->z_head,
1573                                h->z_tail,
1574                                it);
1575   msg_size = sizeof (struct ZoneIterationStopMessage);
1576   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1577   pe->size = msg_size;
1578   pe->is_init = GNUNET_NO;
1579   msg = (struct ZoneIterationStopMessage *) &pe[1];
1580   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1581   msg->gns_header.header.size = htons (msg_size);
1582   msg->gns_header.r_id = htonl (it->op_id);
1583   if (GNUNET_YES == it->has_zone)
1584     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1585                 "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_STOP", GNUNET_short_h2s(&it->zone));
1586   else
1587     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1588                 "Sending `%s' message for all zones\n", "ZONE_ITERATION_STOP");
1589   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1590   do_transmit(h);
1591   GNUNET_free (it);
1592 }
1593
1594
1595 /**
1596  * Cancel a namestore operation.  The final callback from the
1597  * operation must not have been done yet.
1598  *
1599  * @param qe operation to cancel
1600  */
1601 void
1602 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1603 {
1604   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1605
1606   GNUNET_assert (NULL != qe);
1607   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
1608   GNUNET_free(qe);
1609 }
1610
1611 /* end of namestore_api.c */