social: API changes for application connections: store/load app subscriptions to...
[oweals/gnunet.git] / src / sensor / gnunet-service-sensor_update.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C)
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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file sensor/gnunet-service-sensor_update.c
23  * @brief sensor service update functionality
24  * @author Omar Tarabai
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "sensor.h"
29 #include "gnunet_cadet_service.h"
30 #include "gnunet_sensor_model_plugin.h"
31 #include "gnunet_applications.h"
32
33 #define LOG(kind,...) GNUNET_log_from (kind, "sensor-update",__VA_ARGS__)
34
35 /**
36  * Interval at which to contact update points for new sensor updates.
37  */
38 #define SENSOR_UPDATE_CHECK_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
39
40 /**
41  * Interval at which to retry contacting update point if we were busy.
42  */
43 #define SENSOR_UPDATE_CHECK_RETRY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1)
44
45
46 /**
47  * Message queued to be sent to an update point stored in a DLL
48  */
49 struct PendingMessage
50 {
51
52   /**
53    * DLL
54    */
55   struct PendingMessage *prev;
56
57   /**
58    * DLL
59    */
60   struct PendingMessage *next;
61
62   /**
63    * Actual queued message
64    */
65   struct GNUNET_MessageHeader *msg;
66
67 };
68
69 /**
70  * Sensors update point
71  */
72 struct UpdatePoint
73 {
74
75   /**
76    * DLL
77    */
78   struct UpdatePoint *prev;
79
80   /**
81    * DLL
82    */
83   struct UpdatePoint *next;
84
85   /**
86    * Identity of peer running update point
87    */
88   struct GNUNET_PeerIdentity peer_id;
89
90   /**
91    * CADET channel to update point
92    */
93   struct GNUNET_CADET_Channel *ch;
94
95   /**
96    * CADET transmit handle for a message to be sent to update point.
97    */
98   struct GNUNET_CADET_TransmitHandle *th;
99
100   /**
101    * Head of DLL of pending requests to be sent to update point.
102    */
103   struct PendingMessage *pm_head;
104
105   /**
106    * Tail of DLL of pending requests to be sent to update point.
107    */
108   struct PendingMessage *pm_tail;
109
110   /**
111    * Are we waiting for a sensor list?
112    */
113   int expecting_sensor_list;
114
115   /**
116    * How many sensor updates did we request and are waiting for.
117    */
118   int expected_sensor_updates;
119
120   /**
121    * Did a failure occur while dealing with this update point before?
122    */
123   int failed;
124
125 };
126
127
128 /**
129  * Our configuration.
130  */
131 static const struct GNUNET_CONFIGURATION_Handle *cfg;
132
133 /**
134  * Path to sensor definition directory
135  */
136 static char *sensor_dir;
137
138 /**
139  * Hashmap of known sensors
140  */
141 static struct GNUNET_CONTAINER_MultiHashMap *sensors;
142
143 /**
144  * Head of update points DLL.
145  */
146 static struct UpdatePoint *up_head;
147
148 /**
149  * Tail of update points DLL.
150  */
151 static struct UpdatePoint *up_tail;
152
153 /**
154  * The current default update point to use.
155  */
156 static struct UpdatePoint *up_default;
157
158 /**
159  * Handle to CADET service
160  */
161 static struct GNUNET_CADET_Handle *cadet;
162
163 /**
164  * Are we in the process of checking and updating sensors?
165  */
166 static int updating;
167
168 /**
169  * GNUnet scheduler task that starts the update check process.
170  */
171 static struct GNUNET_SCHEDULER_Task * update_task;
172
173 /**
174  * Pointer to service reset function called when we have new sensor updates.
175  */
176 static void (*reset_cb) ();
177
178
179 /**
180  * Contact update points to check for new updates
181  *
182  * @param cls unused
183  * @param tc GNUnet scheduler task context
184  */
185 static void
186 check_for_updates (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
187
188
189 /**
190  * Trigger sending next pending message to the default update point if any.
191  *
192  */
193 static void
194 trigger_send_next_msg ();
195
196
197 /**
198  * Cleanup update point context. This does not destroy the struct itself.
199  *
200  * @param up UpdatePoint struct
201  */
202 static void
203 cleanup_updatepoint (struct UpdatePoint *up)
204 {
205   struct PendingMessage *pm;
206
207   up->expecting_sensor_list = GNUNET_NO;
208   up->expected_sensor_updates = 0;
209   if (NULL != up->th)
210   {
211     GNUNET_CADET_notify_transmit_ready_cancel (up->th);
212     up->th = NULL;
213   }
214   pm = up->pm_head;
215   while (NULL != pm)
216   {
217     GNUNET_CONTAINER_DLL_remove (up->pm_head, up->pm_tail, pm);
218     GNUNET_free (pm->msg);
219     GNUNET_free (pm);
220     pm = up->pm_head;
221   }
222   if (NULL != up->ch)
223   {
224     GNUNET_CADET_channel_destroy (up->ch);
225     up->ch = NULL;
226   }
227 }
228
229
230 /**
231  * Stop the sensor update module.
232  */
233 void
234 SENSOR_update_stop ()
235 {
236   struct UpdatePoint *up;
237
238   up_default = NULL;
239   up = up_head;
240   if (NULL != update_task)
241   {
242     GNUNET_SCHEDULER_cancel (update_task);
243     update_task = NULL;
244   }
245   while (NULL != up)
246   {
247     GNUNET_CONTAINER_DLL_remove (up_head, up_tail, up);
248     cleanup_updatepoint (up);
249     GNUNET_free (up);
250     up = up_head;
251   }
252   if (NULL != cadet)
253   {
254     GNUNET_CADET_disconnect (cadet);
255     cadet = NULL;
256   }
257   if (NULL != sensor_dir)
258   {
259     GNUNET_free (sensor_dir);
260     sensor_dir = NULL;
261   }
262   LOG (GNUNET_ERROR_TYPE_DEBUG, "Sensor update module stopped.\n");
263 }
264
265
266 /**
267  * A failure occured in connecting/retrieval/verification with current default
268  * update point. This method will try to find another update point, do cleanup
269  * and reschedule update check.
270  */
271 static void
272 fail ()
273 {
274   struct UpdatePoint *up;
275
276   cleanup_updatepoint (up_default);
277   if (up_default == up_tail)
278   {
279     LOG (GNUNET_ERROR_TYPE_WARNING,
280          "All defined update points failed. Will retry again in %s.\n",
281          GNUNET_STRINGS_relative_time_to_string (SENSOR_UPDATE_CHECK_INTERVAL,
282                                                  GNUNET_NO));
283     up = up_head;
284     while (NULL != up)
285     {
286       up->failed = GNUNET_NO;
287       up = up->next;
288     }
289     update_task =
290         GNUNET_SCHEDULER_add_delayed (SENSOR_UPDATE_CHECK_INTERVAL,
291                                       &check_for_updates, NULL);
292     return;
293   }
294   LOG (GNUNET_ERROR_TYPE_WARNING,
295        "Update point `%s' failed, trying next one now.\n",
296        GNUNET_i2s (&up_default->peer_id));
297   up_default = up_default->next;
298   update_task = GNUNET_SCHEDULER_add_now (&check_for_updates, NULL);
299 }
300
301
302 /**
303  * Function called to notify a client about the connection begin ready
304  * to queue more data.  @a buf will be NULL and @a size zero if the
305  * connection was closed for writing in the meantime.
306  *
307  * Perform the actual sending of the message to update point.
308  *
309  * @param cls closure (unused)
310  * @param size number of bytes available in @a buf
311  * @param buf where the callee should write the message
312  * @return number of bytes written to @a buf
313  */
314 static size_t
315 do_send_msg (void *cls, size_t size, void *buf)
316 {
317   struct PendingMessage *pm;
318   size_t msg_size;
319
320   up_default->th = NULL;
321   pm = up_default->pm_head;
322   msg_size = ntohs (pm->msg->size);
323   GNUNET_CONTAINER_DLL_remove (up_default->pm_head, up_default->pm_tail, pm);
324   if (NULL == buf || size < msg_size)
325   {
326     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
327                 _("Error trying to send a message to update point `%s'.\n"),
328                 GNUNET_i2s (&up_default->peer_id));
329     fail ();
330     return 0;
331   }
332   memcpy (buf, pm->msg, msg_size);
333   GNUNET_free (pm->msg);
334   GNUNET_free (pm);
335   trigger_send_next_msg ();
336   return msg_size;
337 }
338
339
340 /**
341  * Trigger sending next pending message to the default update point if any.
342  *
343  */
344 static void
345 trigger_send_next_msg ()
346 {
347   struct PendingMessage *pm;
348
349   if (NULL == up_default->pm_head)
350     return;
351   if (NULL != up_default->th)
352     return;
353   pm = up_default->pm_head;
354   up_default->th =
355       GNUNET_CADET_notify_transmit_ready (up_default->ch, GNUNET_YES,
356                                           GNUNET_TIME_UNIT_FOREVER_REL,
357                                           ntohs (pm->msg->size), &do_send_msg,
358                                           NULL);
359 }
360
361
362 /**
363  * Add a message to the queue to be sent to the current default update point.
364  *
365  * @param msg Message to be queued
366  */
367 static void
368 queue_msg (struct GNUNET_MessageHeader *msg)
369 {
370   struct PendingMessage *pm;
371
372   pm = GNUNET_new (struct PendingMessage);
373
374   pm->msg = msg;
375   GNUNET_CONTAINER_DLL_insert_tail (up_default->pm_head, up_default->pm_tail,
376                                     pm);
377   trigger_send_next_msg ();
378 }
379
380
381 /**
382  * Contact update points to check for new updates
383  *
384  * @param cls unused
385  * @param tc GNUnet scheduler task context
386  */
387 static void
388 check_for_updates (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
389 {
390   struct GNUNET_MessageHeader *msg;
391   size_t msg_size;
392
393   update_task = NULL;
394   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
395     return;
396   if (GNUNET_YES == updating)
397   {
398     LOG (GNUNET_ERROR_TYPE_WARNING,
399          "Update process still running and update interval already exhausted."
400          "Retrying in %s.\n",
401          GNUNET_STRINGS_relative_time_to_string (SENSOR_UPDATE_CHECK_RETRY,
402                                                  GNUNET_NO));
403     update_task =
404         GNUNET_SCHEDULER_add_delayed (SENSOR_UPDATE_CHECK_RETRY,
405                                       &check_for_updates, NULL);
406     return;
407   }
408   updating = GNUNET_YES;
409   LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking for sensor updates.\n");
410   GNUNET_assert (NULL != up_default);
411   up_default->ch =
412       GNUNET_CADET_channel_create (cadet, up_default, &up_default->peer_id,
413                                    GNUNET_APPLICATION_TYPE_SENSORUPDATE,
414                                    GNUNET_CADET_OPTION_DEFAULT);
415   if (NULL == up_default->ch)
416   {
417     LOG (GNUNET_ERROR_TYPE_ERROR,
418          _("Failed to connect to update point `%s'.\n"),
419          GNUNET_i2s (&up_default->peer_id));
420     fail ();
421     return;
422   }
423   /* Start by requesting list of sensors available from update point */
424   up_default->expecting_sensor_list = GNUNET_YES;
425   msg = GNUNET_new (struct GNUNET_MessageHeader);
426   msg_size = sizeof (struct GNUNET_MessageHeader);
427   msg->size = htons (msg_size);
428   msg->type = htons (GNUNET_MESSAGE_TYPE_SENSOR_LIST_REQ);
429   queue_msg (msg);
430   update_task =
431       GNUNET_SCHEDULER_add_delayed (SENSOR_UPDATE_CHECK_INTERVAL,
432                                     &check_for_updates, NULL);
433 }
434
435
436 /**
437  * Function that reads and validates (correctness not connectivity) of available
438  * sensor update points.
439  *
440  * @return number of update points loaded successfully
441  */
442 static int
443 load_update_points ()
444 {
445   char *points_list;
446   int points_list_len;
447   int i;
448   int start;
449   int len;
450   struct GNUNET_CRYPTO_EddsaPublicKey public_key;
451   struct UpdatePoint *up;
452   int count = 0;
453
454   if (GNUNET_OK !=
455       GNUNET_CONFIGURATION_get_value_string (cfg, "sensor-update",
456                                              "UPDATE_POINTS", &points_list))
457   {
458     return 0;
459   }
460   points_list_len = strlen (points_list) + 1;
461   for (i = 0; i < points_list_len; i++)
462   {
463     if (' ' == points_list[i])
464       continue;
465     start = i;
466     len = 0;
467     while (' ' != points_list[i] && '\0' != points_list[i])
468     {
469       len++;
470       i++;
471     }
472     if (GNUNET_OK !=
473         GNUNET_CRYPTO_eddsa_public_key_from_string (points_list + start, len,
474                                                     &public_key))
475     {
476       LOG (GNUNET_ERROR_TYPE_ERROR,
477            "Invalid EDDSA public key `%.*s' for update point.\n", len,
478            points_list + len);
479       continue;
480     }
481     up = GNUNET_new (struct UpdatePoint);
482
483     up->peer_id.public_key = public_key;
484     up->ch = NULL;
485     up->th = NULL;
486     up->expecting_sensor_list = GNUNET_NO;
487     up->expected_sensor_updates = 0;
488     up->failed = GNUNET_NO;
489     GNUNET_CONTAINER_DLL_insert (up_head, up_tail, up);
490     count++;
491     LOG (GNUNET_ERROR_TYPE_DEBUG, "Loaded update point `%s'.\n",
492          GNUNET_i2s_full (&up->peer_id));
493   }
494   GNUNET_free (points_list);
495   return count;
496 }
497
498
499 /**
500  * Checks if the given sensor name and version (retrieved from an update point)
501  * is new for us and we would like to install it. This is the case if we don't
502  * have this sensor or we have an old version of it.
503  *
504  * @param sensorname Sensor name
505  * @param sensorversion_major First part of version number
506  * @param sensorversion_minor Second part of version number
507  * @return #GNUNET_YES if we don't have this sensor
508  *         #GNUNET_NO if we have it
509  */
510 static int
511 update_required (char *sensorname, uint16_t sensorversion_major,
512                  uint16_t sensorversion_minor)
513 {
514   struct GNUNET_HashCode key;
515   struct GNUNET_SENSOR_SensorInfo *local_sensor;
516
517   GNUNET_CRYPTO_hash (sensorname, strlen (sensorname) + 1, &key);
518   local_sensor = GNUNET_CONTAINER_multihashmap_get (sensors, &key);
519   if (NULL == local_sensor)
520     return GNUNET_YES;
521   if (GNUNET_SENSOR_version_compare
522       (local_sensor->version_major, local_sensor->version_minor,
523        sensorversion_major, sensorversion_minor) < 0)
524     return GNUNET_YES;
525   return GNUNET_NO;
526 }
527
528
529 /**
530  * Handler of a sensor list message received from an update point.
531  *
532  * @param cls Closure (unused).
533  * @param channel Connection to the other end.
534  * @param channel_ctx Place to store local state associated with the channel.
535  * @param message The actual message.
536  * @return #GNUNET_OK to keep the channel open,
537  *         #GNUNET_SYSERR to close it (signal serious error).
538  */
539 static int
540 handle_sensor_brief (void *cls, struct GNUNET_CADET_Channel *channel,
541                      void **channel_ctx,
542                      const struct GNUNET_MessageHeader *message)
543 {
544   struct GNUNET_SENSOR_SensorBriefMessage *sbm;
545   struct GNUNET_MessageHeader *pull_req;
546   uint16_t version_major;
547   uint16_t version_minor;
548   uint16_t msg_size;
549
550   GNUNET_assert (*channel_ctx == up_default);
551   if (GNUNET_YES != up_default->expecting_sensor_list)
552   {
553     GNUNET_break_op (0);
554     fail ();
555     return GNUNET_OK;
556   }
557   if (GNUNET_MESSAGE_TYPE_SENSOR_END == ntohs (message->type))
558   {
559     LOG (GNUNET_ERROR_TYPE_DEBUG,
560          "Received end of sensor list msg. We already requested %d updates.\n",
561          up_default->expected_sensor_updates);
562     up_default->expecting_sensor_list = GNUNET_NO;
563     if (0 == up_default->expected_sensor_updates)
564     {
565       updating = GNUNET_NO;
566       cleanup_updatepoint (up_default);
567       return GNUNET_OK;
568     }
569   }
570   else
571   {
572     sbm = (struct GNUNET_SENSOR_SensorBriefMessage *) message;
573     version_major = ntohs (sbm->version_major);
574     version_minor = ntohs (sbm->version_minor);
575     if (GNUNET_YES ==
576         update_required ((char *) &sbm[1], version_major, version_minor))
577     {
578       LOG (GNUNET_ERROR_TYPE_INFO,
579            "Requesting sensor %s %d.%d from update point.\n", &sbm[1],
580            version_major, version_minor);
581       /* We duplicate the same msg received but change the type and send it
582        * back to update point to ask for full sensor information. */
583       msg_size = ntohs (message->size);
584       pull_req = GNUNET_malloc (msg_size);
585       memcpy (pull_req, message, msg_size);
586       pull_req->type = htons (GNUNET_MESSAGE_TYPE_SENSOR_FULL_REQ);
587       queue_msg (pull_req);
588       up_default->expected_sensor_updates++;
589     }
590   }
591   GNUNET_CADET_receive_done (channel);
592   return GNUNET_OK;
593 }
594
595
596 /**
597  * Update local sensor definitions with a sensor retrieved from an update point.
598  *
599  * @param sensorname Sensor name
600  * @param sensorfile Buffer containing the sensor definition file
601  * @param sensorfile_size Size of @e sensorfile
602  * @param scriptname Name of associated script file, NULL if no script
603  * @param scriptfile Buffer containing the script file, NULL if no script
604  * @param scriptfile_size Size of @e scriptfile, 0 if no script
605  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
606  */
607 static int
608 update_sensor (char *sensorname, void *sensorfile, uint16_t sensorfile_size,
609                char *scriptname, void *scriptfile, uint16_t scriptfile_size)
610 {
611   char *sensor_path;
612   char *script_path;
613
614   LOG (GNUNET_ERROR_TYPE_INFO,
615        "Received new sensor information:\n" "Name: %s\n"
616        "Sensor file size: %d\n" "Script name: %s\n" "Script file size: %d.\n",
617        sensorname, sensorfile_size, (NULL == scriptname) ? "None" : scriptname,
618        scriptfile_size);
619   GNUNET_asprintf (&sensor_path, "%s%s", sensor_dir, sensorname);
620   GNUNET_DISK_fn_write (sensor_path, sensorfile, sensorfile_size,
621                         GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_GROUP_READ
622                         | GNUNET_DISK_PERM_OTHER_READ |
623                         GNUNET_DISK_PERM_USER_WRITE);
624   if (NULL != scriptname)
625   {
626     GNUNET_asprintf (&script_path, "%s-files%s%s", sensor_path,
627                      DIR_SEPARATOR_STR, scriptname);
628     GNUNET_DISK_fn_write (script_path, scriptfile, scriptfile_size,
629                           GNUNET_DISK_PERM_USER_READ |
630                           GNUNET_DISK_PERM_GROUP_READ |
631                           GNUNET_DISK_PERM_OTHER_READ |
632                           GNUNET_DISK_PERM_USER_WRITE |
633                           GNUNET_DISK_PERM_GROUP_WRITE |
634                           GNUNET_DISK_PERM_USER_EXEC |
635                           GNUNET_DISK_PERM_GROUP_EXEC);
636     GNUNET_free (script_path);
637   }
638   GNUNET_free (sensor_path);
639   return GNUNET_OK;
640 }
641
642
643 /**
644  * Resets the service after we are done with an update.
645  *
646  * @param cls unused
647  * @param tc unused
648  */
649 static void
650 reset (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
651 {
652   reset_cb ();
653 }
654
655
656 /**
657  * Handler of a sensor list message received from an update point.
658  *
659  * @param cls Closure (unused).
660  * @param channel Connection to the other end.
661  * @param channel_ctx Place to store local state associated with the channel.
662  * @param message The actual message.
663  * @return #GNUNET_OK to keep the channel open,
664  *         #GNUNET_SYSERR to close it (signal serious error).
665  */
666 static int
667 handle_sensor_full (void *cls, struct GNUNET_CADET_Channel *channel,
668                     void **channel_ctx,
669                     const struct GNUNET_MessageHeader *message)
670 {
671   struct GNUNET_SENSOR_SensorFullMessage *sfm;
672   uint16_t msg_size;
673   uint16_t sensorfile_size;
674   uint16_t scriptfile_size;
675   char *sensorname_ptr;
676   void *sensorfile_ptr;
677   char *scriptname_ptr;
678   void *scriptfile_ptr;
679
680   /* error check */
681   GNUNET_assert (*channel_ctx == up_default);
682   msg_size = ntohs (message->size);
683   if (up_default->expected_sensor_updates <= 0 ||
684       msg_size < sizeof (struct GNUNET_SENSOR_SensorFullMessage))
685   {
686     GNUNET_break_op (0);
687     fail ();
688     return GNUNET_OK;
689   }
690   /* parse received msg */
691   sfm = (struct GNUNET_SENSOR_SensorFullMessage *) message;
692   sensorname_ptr = (char *) &sfm[1];
693   sensorfile_ptr = sensorname_ptr + ntohs (sfm->sensorname_size);
694   sensorfile_size = ntohs (sfm->sensorfile_size);
695   scriptfile_size = ntohs (sfm->scriptfile_size);
696   if (scriptfile_size > 0)
697   {
698     scriptname_ptr = sensorfile_ptr + sensorfile_size;
699     scriptfile_ptr = scriptname_ptr + ntohs (sfm->scriptname_size);
700   }
701   else
702   {
703     scriptname_ptr = NULL;
704     scriptfile_ptr = NULL;
705   }
706   update_sensor ((char *) &sfm[1], sensorfile_ptr, sensorfile_size,
707                  scriptname_ptr, scriptfile_ptr, scriptfile_size);
708   up_default->expected_sensor_updates--;
709   if (0 == up_default->expected_sensor_updates)
710   {
711     updating = GNUNET_NO;
712     cleanup_updatepoint (up_default);
713     GNUNET_SCHEDULER_add_now (&reset, NULL);
714   }
715   else
716     GNUNET_CADET_receive_done (channel);
717   return GNUNET_OK;
718 }
719
720
721 /**
722  * Function called whenever a channel is destroyed.  Should clean up
723  * any associated state.
724  *
725  * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
726  *
727  * @param cls closure (set from #GNUNET_CADET_connect)
728  * @param channel connection to the other end (henceforth invalid)
729  * @param channel_ctx place where local state associated
730  *                   with the channel is stored
731  */
732 static void
733 cadet_channel_destroyed (void *cls, const struct GNUNET_CADET_Channel *channel,
734                          void *channel_ctx)
735 {
736   struct UpdatePoint *up = channel_ctx;
737
738   up->ch = NULL;
739   if (GNUNET_YES == updating)
740   {
741     fail ();
742     return;
743   }
744   cleanup_updatepoint (up);
745 }
746
747
748 /**
749  * Start the sensor update module
750  *
751  * @param c our service configuration
752  * @param s multihashmap of loaded sensors
753  * @param cb callback to reset service components when we have new updates
754  * @return #GNUNET_OK if started successfully, #GNUNET_SYSERR otherwise
755  */
756 int
757 SENSOR_update_start (const struct GNUNET_CONFIGURATION_Handle *c,
758                      struct GNUNET_CONTAINER_MultiHashMap *s, void (*cb) ())
759 {
760   static struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
761     {&handle_sensor_brief, GNUNET_MESSAGE_TYPE_SENSOR_BRIEF, 0},
762     {&handle_sensor_brief, GNUNET_MESSAGE_TYPE_SENSOR_END, 0},
763     {&handle_sensor_full, GNUNET_MESSAGE_TYPE_SENSOR_FULL, 0},
764     {NULL, 0, 0}
765   };
766   int up_count;
767
768   GNUNET_assert (NULL != s);
769   cfg = c;
770   sensors = s;
771   reset_cb = cb;
772   if (GNUNET_OK !=
773       GNUNET_CONFIGURATION_get_value_filename (cfg, "SENSOR", "SENSOR_DIR",
774                                                &sensor_dir))
775     sensor_dir = GNUNET_SENSOR_get_default_sensor_dir ();
776   cadet =
777       GNUNET_CADET_connect (cfg, NULL, NULL, &cadet_channel_destroyed,
778                             cadet_handlers, NULL);
779   if (NULL == cadet)
780   {
781     LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to CADET service.\n"));
782     SENSOR_update_stop ();
783     return GNUNET_SYSERR;
784   }
785   up_count = load_update_points ();
786   LOG (GNUNET_ERROR_TYPE_DEBUG, "Loaded %d update points.\n", up_count);
787   if (0 == up_count)
788   {
789     SENSOR_update_stop ();
790     return GNUNET_SYSERR;
791   }
792   up_default = up_head;
793   updating = GNUNET_NO;
794   update_task =
795       GNUNET_SCHEDULER_add_delayed (SENSOR_UPDATE_CHECK_INTERVAL,
796                                     &check_for_updates, NULL);
797   LOG (GNUNET_ERROR_TYPE_DEBUG, "Sensor update module started.\n");
798   return GNUNET_OK;
799 }
800
801 /* end of gnunet-service-sensor_update.c */