-handle failure to load certs more nicely
[oweals/gnunet.git] / src / psycstore / gnunet-service-psycstore.c
1 /*
2  * This file is part of GNUnet
3  * (C) 2013 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 psycstore/gnunet-service-psycstore.c
23  * @brief PSYCstore service
24  * @author Gabor X Toth
25  * @author Christian Grothoff
26  */
27
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_statistics_service.h"
33 #include "gnunet_psycstore_service.h"
34 #include "gnunet_psycstore_plugin.h"
35 #include "psycstore.h"
36
37
38 /**
39  * Handle to our current configuration.
40  */
41 static const struct GNUNET_CONFIGURATION_Handle *cfg;
42
43 /**
44  * Handle to the statistics service.
45  */
46 static struct GNUNET_STATISTICS_Handle *stats;
47
48 /**
49  * Notification context, simplifies client broadcasts.
50  */
51 static struct GNUNET_SERVER_NotificationContext *nc;
52
53 /**
54  * Database handle
55  */
56 static struct GNUNET_PSYCSTORE_PluginFunctions *db;
57
58 /**
59  * Name of the database plugin
60  */
61 static char *db_lib_name;
62
63
64 /**
65  * Task run during shutdown.
66  *
67  * @param cls unused
68  * @param tc unused
69  */
70 static void
71 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
72 {
73   if (NULL != nc)
74   {
75     GNUNET_SERVER_notification_context_destroy (nc);
76     nc = NULL;
77   }
78   if (NULL != stats)
79   {
80     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
81     stats = NULL;
82   }
83   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db));
84   GNUNET_free (db_lib_name);
85   db_lib_name = NULL;
86 }
87
88
89 /** 
90  * Send a result code back to the client.
91  *
92  * @param client Client that should receive the result code.
93  * @param result_code Code to transmit.
94  * @param op_id Operation ID.
95  * @param err_msg Error message to include (or NULL for none).
96  */
97 static void
98 send_result_code (struct GNUNET_SERVER_Client *client, uint32_t result_code,
99                   uint32_t op_id, const char *err_msg)
100 {
101   struct OperationResult *res;
102   size_t err_len;
103
104   if (NULL == err_msg)
105     err_len = 0;
106   else
107     err_len = strlen (err_msg) + 1;
108   res = GNUNET_malloc (sizeof (struct OperationResult) + err_len);
109   res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE);
110   res->header.size = htons (sizeof (struct OperationResult) + err_len);
111   res->result_code = htonl (result_code);
112   res->op_id = op_id;
113   if (0 < err_len)
114     memcpy (&res[1], err_msg, err_len);
115   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
116               "Sending result %d (%s) to client\n",
117               (int) result_code,
118               err_msg);
119   GNUNET_SERVER_notification_context_add (nc, client);
120   GNUNET_SERVER_notification_context_unicast (nc, client, &res->header,
121                                               GNUNET_NO);
122   GNUNET_free (res);
123 }
124
125
126 struct SendClosure
127 {
128   struct GNUNET_SERVER_Client *client;
129   uint64_t op_id;
130 };
131
132
133 static int
134 send_fragment (void *cls, struct GNUNET_MULTICAST_MessageHeader *msg,
135                enum GNUNET_PSYCSTORE_MessageFlags flags)
136 {
137   struct SendClosure *sc = cls;
138   struct FragmentResult *res;
139   size_t msg_size = ntohs (msg->header.size);
140
141   res = GNUNET_malloc (sizeof (struct FragmentResult) + msg_size);
142   res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_FRAGMENT);
143   res->header.size = htons (sizeof (struct FragmentResult) + msg_size);
144   res->op_id = sc->op_id;
145   res->psycstore_flags = htonl (flags);
146   memcpy (&res[1], msg, msg_size);
147   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
148               "Sending fragment %ld to client\n",
149               GNUNET_ntohll (msg->fragment_id));
150   GNUNET_free (msg);
151   GNUNET_SERVER_notification_context_add (nc, sc->client);
152   GNUNET_SERVER_notification_context_unicast (nc, sc->client, &res->header,
153                                               GNUNET_NO);
154   GNUNET_free (res);
155   return GNUNET_OK;
156 }
157
158
159 static int
160 send_state_var (void *cls, const char *name,
161                 const void *value, size_t value_size)
162 {
163   struct SendClosure *sc = cls;
164   struct StateResult *res;
165   size_t name_size = strlen (name) + 1;
166
167   res = GNUNET_malloc (sizeof (struct StateResult) + name_size + value_size);
168   res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_STATE);
169   res->header.size = htons (sizeof (struct StateResult) + name_size + value_size);
170   res->op_id = sc->op_id;
171   res->name_size = htons (name_size);
172   memcpy (&res[1], name, name_size);
173   memcpy ((void *) &res[1] + name_size, value, value_size);
174   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
175               "Sending state variable %s to client\n", name);
176   GNUNET_SERVER_notification_context_add (nc, sc->client);
177   GNUNET_SERVER_notification_context_unicast (nc, sc->client, &res->header,
178                                               GNUNET_NO);
179   GNUNET_free (res);
180   return GNUNET_OK;
181 }
182
183
184 static void
185 handle_membership_store (void *cls,
186                          struct GNUNET_SERVER_Client *client,
187                          const struct GNUNET_MessageHeader *msg)
188 {
189   const struct MembershipStoreRequest *req =
190     (const struct MembershipStoreRequest *) msg;
191
192   int ret = db->membership_store (db->cls, &req->channel_key, &req->slave_key,
193                                   ntohl (req->did_join),
194                                   GNUNET_ntohll (req->announced_at),
195                                   GNUNET_ntohll (req->effective_since),
196                                   GNUNET_ntohll (req->group_generation));
197
198   if (ret != GNUNET_OK)
199     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
200                 _("Failed to store membership information!\n"));
201
202   send_result_code (client, ret, req->op_id, NULL);
203   GNUNET_SERVER_receive_done (client, GNUNET_OK);
204 }
205
206
207 static void
208 handle_membership_test (void *cls,
209                         struct GNUNET_SERVER_Client *client,
210                         const struct GNUNET_MessageHeader *msg)
211 {
212   const struct MembershipTestRequest *req =
213     (const struct MembershipTestRequest *) msg;
214
215   int ret = db->membership_test (db->cls, &req->channel_key, &req->slave_key,
216                                  GNUNET_ntohll (req->message_id));
217   switch (ret)
218   {
219   case GNUNET_YES:
220   case GNUNET_NO:
221     break;
222   default:
223     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
224                 _("Failed to test membership!\n"));
225   }
226
227   send_result_code (client, ret, req->op_id, NULL);
228   GNUNET_SERVER_receive_done (client, GNUNET_OK);
229 }
230
231
232 static void
233 handle_fragment_store (void *cls,
234                        struct GNUNET_SERVER_Client *client,
235                        const struct GNUNET_MessageHeader *msg)
236 {
237   const struct FragmentStoreRequest *req =
238     (const struct FragmentStoreRequest *) msg;
239
240   int ret = db->fragment_store (db->cls, &req->channel_key,
241                                 (const struct GNUNET_MULTICAST_MessageHeader *)
242                                 &req[1], ntohl (req->psycstore_flags));
243
244   if (ret != GNUNET_OK)
245     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
246                 _("Failed to store fragment!\n"));
247
248   send_result_code (client, ret, req->op_id, NULL);
249   GNUNET_SERVER_receive_done (client, GNUNET_OK);
250 }
251
252
253 static void
254 handle_fragment_get (void *cls,
255                      struct GNUNET_SERVER_Client *client,
256                      const struct GNUNET_MessageHeader *msg)
257 {
258   const struct FragmentGetRequest *req
259     = (const struct FragmentGetRequest *) msg;
260   struct SendClosure sc = { .op_id = req->op_id, .client = client };
261
262   int ret = db->fragment_get (db->cls, &req->channel_key,
263                               GNUNET_ntohll (req->fragment_id),
264                               &send_fragment, &sc);
265   switch (ret)
266   {
267   case GNUNET_YES:
268   case GNUNET_NO:
269     break;
270   default:
271     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
272                 _("Failed to get fragment!\n"));
273   }
274
275   send_result_code (client, ret, req->op_id, NULL);
276   GNUNET_SERVER_receive_done (client, GNUNET_OK);
277 }
278
279
280 static void
281 handle_message_get (void *cls,
282                     struct GNUNET_SERVER_Client *client,
283                     const struct GNUNET_MessageHeader *msg)
284 {
285   const struct MessageGetRequest *req = (const struct MessageGetRequest *) msg;
286   struct SendClosure sc = { .op_id = req->op_id, .client = client };
287   uint64_t ret_frags = 0;
288   int64_t ret = db->message_get (db->cls, &req->channel_key,
289                                  GNUNET_ntohll (req->message_id),
290                                  &ret_frags, &send_fragment, &sc);
291   switch (ret)
292   {
293   case GNUNET_YES:
294   case GNUNET_NO:
295     break;
296   default:
297     ret_frags = ret;
298     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
299                 _("Failed to get message!\n"));
300   }
301
302   send_result_code (client, ret_frags, req->op_id, NULL);
303   GNUNET_SERVER_receive_done (client, GNUNET_OK);
304 }
305
306
307 static void
308 handle_message_get_fragment (void *cls,
309                              struct GNUNET_SERVER_Client *client,
310                              const struct GNUNET_MessageHeader *msg)
311 {
312   const struct MessageGetFragmentRequest *req =
313     (const struct MessageGetFragmentRequest *) msg;
314
315   struct SendClosure sc = { .op_id = req->op_id, .client = client };
316
317   int ret = db->message_get_fragment (db->cls, &req->channel_key,
318                                       GNUNET_ntohll (req->message_id),
319                                       GNUNET_ntohll (req->fragment_offset),
320                                       &send_fragment, &sc);
321   switch (ret)
322   {
323   case GNUNET_YES:
324   case GNUNET_NO:
325     break;
326   default:
327     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
328                 _("Failed to get message fragment!\n"));
329   }
330
331   send_result_code (client, ret, req->op_id, NULL);
332   GNUNET_SERVER_receive_done (client, GNUNET_OK);
333 }
334
335
336 static void
337 handle_counters_get_master (void *cls,
338                             struct GNUNET_SERVER_Client *client,
339                             const struct GNUNET_MessageHeader *msg)
340 {
341   const struct OperationRequest *req = (const struct OperationRequest *) msg;
342   struct MasterCountersResult res = { {0} };
343
344   int ret = db->counters_get_master (db->cls, &req->channel_key,
345                                      &res.fragment_id, &res.message_id,
346                                      &res.group_generation);
347   switch (ret)
348   {
349   case GNUNET_YES:
350   case GNUNET_NO:
351     break;
352   default:
353     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
354                 _("Failed to get master counters!\n"));
355   }
356
357   res.header.type
358     = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS_MASTER);
359   res.header.size = htons (sizeof (res));
360   res.result_code = htonl (ret);
361   res.op_id = req->op_id;
362   res.fragment_id = GNUNET_htonll (res.fragment_id);
363   res.message_id = GNUNET_htonll (res.message_id);
364   res.group_generation = GNUNET_htonll (res.group_generation);
365
366   GNUNET_SERVER_notification_context_add (nc, client);
367   GNUNET_SERVER_notification_context_unicast (nc, client, &res.header,
368                                               GNUNET_NO);
369
370   GNUNET_SERVER_receive_done (client, GNUNET_OK);
371 }
372
373
374 static void
375 handle_counters_get_slave (void *cls,
376                            struct GNUNET_SERVER_Client *client,
377                            const struct GNUNET_MessageHeader *msg)
378 {
379   const struct OperationRequest *req = (const struct OperationRequest *) msg;
380   struct SlaveCountersResult res = { {0} };
381
382   int ret = db->counters_get_slave (db->cls, &req->channel_key,
383                                     &res.max_known_msg_id);
384
385   switch (ret)
386   {
387   case GNUNET_YES:
388   case GNUNET_NO:
389     break;
390   default:
391     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
392                 _("Failed to get slave counters!\n"));
393   }
394
395   res.header.type
396     = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS_SLAVE);
397   res.header.size = htons (sizeof (res));
398   res.result_code = htonl (ret);
399   res.op_id = req->op_id;
400   res.max_known_msg_id = GNUNET_htonll (res.max_known_msg_id);
401
402   GNUNET_SERVER_notification_context_add (nc, client);
403   GNUNET_SERVER_notification_context_unicast (nc, client, &res.header,
404                                               GNUNET_NO);
405
406   GNUNET_SERVER_receive_done (client, GNUNET_OK);
407 }
408
409
410 /* FIXME: stop processing further state modify messages after an error */
411 static void
412 handle_state_modify (void *cls,
413                      struct GNUNET_SERVER_Client *client,
414                      const struct GNUNET_MessageHeader *msg)
415 {
416   const struct StateModifyRequest *req
417     = (const struct StateModifyRequest *) msg;
418
419   int ret = GNUNET_SYSERR;
420   const char *name = (const char *) &req[1];
421   uint16_t name_size = ntohs (req->name_size);
422
423   if (name_size <= 2 || '\0' != name[name_size - 1])
424   {
425     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
426                 _("Tried to set invalid state variable name!\n"));
427     GNUNET_break_op (0);
428   }
429   else
430   {
431     ret = GNUNET_OK;
432
433     if (req->flags & STATE_OP_FIRST)
434     {
435       ret = db->state_modify_begin (db->cls, &req->channel_key,
436                                     GNUNET_ntohll (req->message_id),
437                                     GNUNET_ntohll (req->state_delta));
438     }
439     if (ret != GNUNET_OK)
440     {
441       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
442                   _("Failed to begin modifying state!\n"));
443     }
444     else
445     {
446       switch (req->oper)
447       {
448       case GNUNET_ENV_OP_ASSIGN:
449         ret = db->state_modify_set (db->cls, &req->channel_key,
450                                     (const char *) &req[1],
451                                     name + ntohs (req->name_size),
452                                     ntohs (req->header.size) - sizeof (*req)
453                                     - ntohs (req->name_size));
454         break;
455       default:
456 #if TODO
457         ret = GNUNET_ENV_operation ((const char *) &req[1],
458                                     current_value, current_value_size,
459                                     req->oper, name + ntohs (req->name_size),
460                                     ntohs (req->header.size) - sizeof (*req)
461                                     - ntohs (req->name_size), &value, &value_size);
462 #endif
463         ret = GNUNET_SYSERR;
464         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
465                     _("Unknown operator: %c\n"), req->oper);
466       }
467     }
468
469     if (GNUNET_OK == ret && req->flags & STATE_OP_LAST)
470     {
471       ret = db->state_modify_end (db->cls, &req->channel_key,
472                                   GNUNET_ntohll (req->message_id));
473       if (ret != GNUNET_OK)
474         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
475                     _("Failed to end modifying state!\n"));
476     }
477   }
478   send_result_code (client, ret, req->op_id, NULL);
479   GNUNET_SERVER_receive_done (client, GNUNET_OK);
480 }
481
482
483 /* FIXME: stop processing further state sync messages after an error */
484 static void
485 handle_state_sync (void *cls,
486                    struct GNUNET_SERVER_Client *client,
487                    const struct GNUNET_MessageHeader *msg)
488 {
489   const struct StateSyncRequest *req
490     = (const struct StateSyncRequest *) msg;
491
492   int ret = GNUNET_SYSERR;
493   const char *name = (const char *) &req[1];
494   uint16_t name_size = ntohs (req->name_size);
495
496   if (name_size <= 2 || '\0' != name[name_size - 1])
497   {
498     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
499                 _("Tried to set invalid state variable name!\n"));
500     GNUNET_break_op (0);
501   }
502   else
503   {
504     ret = GNUNET_OK;
505
506     if (req->flags & STATE_OP_FIRST)
507     {
508       ret = db->state_sync_begin (db->cls, &req->channel_key);
509     }
510     if (ret != GNUNET_OK)
511     {
512       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
513                   _("Failed to begin synchronizing state!\n"));
514     }
515     else
516     {
517       ret = db->state_sync_set (db->cls, &req->channel_key, name,
518                                 name + ntohs (req->name_size),
519                                 ntohs (req->header.size) - sizeof (*req)
520                                 - ntohs (req->name_size));
521     }
522
523     if (GNUNET_OK == ret && req->flags & STATE_OP_LAST)
524     {
525       ret = db->state_sync_end (db->cls, &req->channel_key,
526                                 GNUNET_ntohll (req->message_id));
527       if (ret != GNUNET_OK)
528         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
529                     _("Failed to end synchronizing state!\n"));
530     }
531   }
532   send_result_code (client, ret, req->op_id, NULL);
533   GNUNET_SERVER_receive_done (client, GNUNET_OK);
534 }
535
536
537 static void
538 handle_state_reset (void *cls,
539                     struct GNUNET_SERVER_Client *client,
540                     const struct GNUNET_MessageHeader *msg)
541 {
542   const struct OperationRequest *req =
543     (const struct OperationRequest *) msg;
544
545   int ret = db->state_reset (db->cls, &req->channel_key);
546
547   if (ret != GNUNET_OK)
548     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
549                 _("Failed to reset state!\n"));
550
551   send_result_code (client, ret, req->op_id, NULL);
552   GNUNET_SERVER_receive_done (client, GNUNET_OK);
553 }
554
555
556 static void
557 handle_state_hash_update (void *cls,
558                           struct GNUNET_SERVER_Client *client,
559                           const struct GNUNET_MessageHeader *msg)
560 {
561   const struct OperationRequest *req =
562     (const struct OperationRequest *) msg;
563
564   int ret = db->state_reset (db->cls, &req->channel_key);
565
566   if (ret != GNUNET_OK)
567     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
568                 _("Failed to reset state!\n"));
569
570   send_result_code (client, ret, req->op_id, NULL);
571   GNUNET_SERVER_receive_done (client, GNUNET_OK);
572 }
573
574
575 static void
576 handle_state_get (void *cls,
577                   struct GNUNET_SERVER_Client *client,
578                   const struct GNUNET_MessageHeader *msg)
579 {
580   const struct OperationRequest *req =
581     (const struct OperationRequest *) msg;
582
583   struct SendClosure sc = { .op_id = req->op_id, .client = client };
584   int64_t ret = GNUNET_SYSERR;
585   const char *name = (const char *) &req[1];
586   uint16_t name_size = ntohs (req->header.size) - sizeof (*req);
587
588   if (name_size <= 2 || '\0' != name[name_size - 1])
589   {
590     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
591                 _("Tried to get invalid state variable name!\n"));
592     GNUNET_break (0);
593   }
594   else
595   {
596     ret = db->state_get (db->cls, &req->channel_key, name,
597                          &send_state_var, &sc);
598     if (GNUNET_NO == ret && name_size >= 5) /* min: _a_b\0 */
599     {
600       char *p, *n = GNUNET_malloc (name_size);
601       memcpy (n, name, name_size);
602       while (&n[1] < (p = strrchr (n, '_')) && GNUNET_NO == ret)
603       {
604         *p = '\0';
605         ret = db->state_get (db->cls, &req->channel_key, n,
606                              &send_state_var, &sc);
607       }
608       GNUNET_free (n);
609     }
610   }
611   switch (ret)
612   {
613   case GNUNET_OK:
614   case GNUNET_NO:
615     break;
616   default:
617     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
618                 _("Failed to get state variable!\n"));
619   }
620
621   send_result_code (client, ret, req->op_id, NULL);
622   GNUNET_SERVER_receive_done (client, GNUNET_OK);
623 }
624
625
626 static void
627 handle_state_get_prefix (void *cls,
628                          struct GNUNET_SERVER_Client *client,
629                          const struct GNUNET_MessageHeader *msg)
630 {
631   const struct OperationRequest *req =
632     (const struct OperationRequest *) msg;
633
634   struct SendClosure sc = { .op_id = req->op_id, .client = client };
635   int64_t ret = GNUNET_SYSERR;
636   const char *name = (const char *) &req[1];
637   uint16_t name_size = ntohs (req->header.size) - sizeof (*req);
638
639   if (name_size <= 1 || '\0' != name[name_size - 1])
640   {
641     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
642                 _("Tried to get invalid state variable name!\n"));
643     GNUNET_break (0);
644   }
645   else
646   {
647     ret = db->state_get_prefix (db->cls, &req->channel_key, name,
648                                 &send_state_var, &sc);
649   }
650   switch (ret)
651   {
652   case GNUNET_OK:
653   case GNUNET_NO:
654     break;
655   default:
656     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
657                 _("Failed to get state variable!\n"));
658   }
659
660   send_result_code (client, ret, req->op_id, NULL);
661   GNUNET_SERVER_receive_done (client, GNUNET_OK);
662 }
663
664
665 /**
666  * Initialize the PSYCstore service.
667  *
668  * @param cls Closure.
669  * @param server The initialized server.
670  * @param c Configuration to use.
671  */
672 static void
673 run (void *cls, struct GNUNET_SERVER_Handle *server,
674      const struct GNUNET_CONFIGURATION_Handle *c)
675 {
676   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
677     { &handle_membership_store, NULL,
678       GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_STORE,
679       sizeof (struct MembershipStoreRequest) },
680
681     { &handle_membership_test, NULL,
682       GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST,
683       sizeof (struct MembershipTestRequest) },
684
685     { &handle_fragment_store, NULL,
686       GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_STORE, 0, },
687
688     { &handle_fragment_get, NULL,
689       GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET,
690       sizeof (struct FragmentGetRequest) },
691
692     { &handle_message_get, NULL,
693       GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET,
694       sizeof (struct MessageGetRequest) },
695
696     { &handle_message_get_fragment, NULL,
697       GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET_FRAGMENT,
698       sizeof (struct MessageGetFragmentRequest) },
699
700     { &handle_counters_get_master, NULL,
701       GNUNET_MESSAGE_TYPE_PSYCSTORE_COUNTERS_GET_MASTER,
702       sizeof (struct OperationRequest) },
703
704     { &handle_counters_get_slave, NULL,
705       GNUNET_MESSAGE_TYPE_PSYCSTORE_COUNTERS_GET_SLAVE,
706       sizeof (struct OperationRequest) },
707
708     { &handle_state_modify, NULL,
709       GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY, 0 },
710
711     { &handle_state_sync, NULL,
712       GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC, 0 },
713
714     { &handle_state_reset, NULL,
715       GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_RESET,
716       sizeof (struct OperationRequest) },
717
718     { &handle_state_hash_update, NULL,
719       GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_HASH_UPDATE,
720       sizeof (struct StateHashUpdateRequest) },
721
722     { &handle_state_get, NULL,
723       GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET, 0 },
724
725     { &handle_state_get_prefix, NULL,
726       GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET_PREFIX, 0 },
727
728     { NULL, NULL, 0, 0 }
729   };
730
731   cfg = c;
732
733   /* Loading database plugin */
734   char *database;
735   if (GNUNET_OK !=
736       GNUNET_CONFIGURATION_get_value_string (cfg, "psycstore", "database",
737                                              &database))
738   {
739     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
740   }
741   else
742   {
743     GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_psycstore_%s", database);
744     db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
745     GNUNET_free (database);
746   }
747   if (NULL == db)
748   {
749     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
750                 "Could not load database backend `%s'\n",
751                 db_lib_name);
752     GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
753     return;
754   }
755
756   stats = GNUNET_STATISTICS_create ("psycstore", cfg);
757   GNUNET_SERVER_add_handlers (server, handlers);
758   nc = GNUNET_SERVER_notification_context_create (server, 1);
759   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
760                                 NULL);
761 }
762
763
764 /**
765  * The main function for the service.
766  *
767  * @param argc number of arguments from the command line
768  * @param argv command line arguments
769  * @return 0 ok, 1 on error
770  */
771 int
772 main (int argc, char *const *argv)
773 {
774   return (GNUNET_OK ==
775           GNUNET_SERVICE_run (argc, argv, "psycstore",
776                               GNUNET_SERVICE_OPTION_NONE,
777                               &run, NULL)) ? 0 : 1;
778 }
779
780
781 /* end of gnunet-service-psycstore.c */