config fix
[oweals/gnunet.git] / src / sensordashboard / gnunet-service-sensordashboard.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 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 sensordashboard/gnunet-service-sensordashboard.c
23  * @brief Service collecting sensor readings from peers
24  * @author Omar Tarabai
25  */
26 #include <inttypes.h>
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_applications.h"
30 #include "sensordashboard.h"
31 #include "gnunet_cadet_service.h"
32 #include "gnunet_sensor_util_lib.h"
33 #include "gnunet_peerstore_service.h"
34
35 /**
36  * Handle to CADET service
37  */
38 static struct GNUNET_CADET_Handle *cadet;
39
40 /**
41  * Global hashmap of defined sensors
42  */
43 static struct GNUNET_CONTAINER_MultiHashMap *sensors;
44
45 /**
46  * Handle to the peerstore service connection
47  */
48 static struct GNUNET_PEERSTORE_Handle *peerstore;
49
50 /**
51  * Name of this subsystem to be used for peerstore operations
52  */
53 static char *subsystem = "sensordashboard";
54
55 /**
56  * Task run during shutdown.
57  *
58  * @param cls unused
59  * @param tc unused
60  */
61 static void
62 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
63 {
64   if (NULL != cadet)
65   {
66     GNUNET_CADET_disconnect(cadet);
67     cadet = NULL;
68   }
69   if (NULL != peerstore)
70   {
71     GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_YES);
72     peerstore = NULL;
73   }
74   GNUNET_SENSOR_destroy_sensors (sensors);
75   GNUNET_SCHEDULER_shutdown();
76 }
77
78 /**
79  * Function called whenever a channel is destroyed.  Should clean up
80  * any associated state.
81  *
82  * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
83  *
84  * @param cls closure (set from #GNUNET_CADET_connect)
85  * @param channel connection to the other end (henceforth invalid)
86  * @param channel_ctx place where local state associated
87  *                   with the channel is stored
88  */
89 static void cadet_channel_destroyed (void *cls,
90     const struct GNUNET_CADET_Channel *channel,
91     void *channel_ctx)
92 {
93   struct GNUNET_PeerIdentity *peer = channel_ctx;
94
95   GNUNET_free (peer);
96 }
97
98 /**
99  * Method called whenever another peer has added us to a channel
100  * the other peer initiated.
101  * Only called (once) upon reception of data with a message type which was
102  * subscribed to in #GNUNET_CADET_connect.
103  *
104  * A call to #GNUNET_CADET_channel_destroy causes the channel to be ignored. In
105  * this case the handler MUST return NULL.
106  *
107  * @param cls closure
108  * @param channel new handle to the channel
109  * @param initiator peer that started the channel
110  * @param port Port this channel is for.
111  * @param options CadetOption flag field, with all active option bits set to 1.
112  *
113  * @return initial channel context for the channel
114  *         (can be NULL -- that's not an error)
115  */
116 static void *cadet_channel_created (void *cls,
117     struct GNUNET_CADET_Channel *channel,
118     const struct GNUNET_PeerIdentity *initiator,
119     uint32_t port, enum GNUNET_CADET_ChannelOption options)
120 {
121   struct GNUNET_PeerIdentity *peer;
122
123   peer = GNUNET_new (struct GNUNET_PeerIdentity);
124   memcpy (peer, initiator, sizeof (struct GNUNET_PeerIdentity));
125   return peer;
126 }
127
128 /**
129  * Called with any sensor reading messages received from CADET.
130  *
131  * Each time the function must call #GNUNET_CADET_receive_done on the channel
132  * in order to receive the next message. This doesn't need to be immediate:
133  * can be delayed if some processing is done on the message.
134  *
135  * @param cls Closure (set from #GNUNET_CADET_connect).
136  * @param channel Connection to the other end.
137  * @param channel_ctx Place to store local state associated with the channel.
138  * @param message The actual message.
139  * @return #GNUNET_OK to keep the channel open,
140  *         #GNUNET_SYSERR to close it (signal serious error).
141  */
142 int sensor_reading_receiver (void *cls, struct GNUNET_CADET_Channel *channel,
143     void **channel_ctx, const struct GNUNET_MessageHeader *message)
144 {
145   struct GNUNET_PeerIdentity *peer = *channel_ctx;
146   struct GNUNET_SENSOR_Reading *reading;
147
148   reading = GNUNET_SENSOR_parse_reading_message (message, sensors);
149   if (NULL == reading)
150   {
151     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
152         "Received an invalid sensor reading from peer `%s'\n",
153         GNUNET_i2s (peer));
154     return GNUNET_SYSERR;
155   }
156   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
157       "Received a sensor reading from peer `%s':\n"
158       "# Sensor name: `%s'\n"
159       "# Timestamp: %" PRIu64 "\n"
160       "# Value size: %" PRIu64 ".\n",
161       GNUNET_i2s (peer),
162       reading->sensor->name,
163       reading->timestamp,
164       reading->value_size);
165   GNUNET_PEERSTORE_store (peerstore, subsystem, peer, reading->sensor->name,
166       reading->value, reading->value_size, GNUNET_TIME_UNIT_FOREVER_ABS,
167       GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, NULL, NULL);
168   GNUNET_free (reading->value);
169   GNUNET_free (reading);
170   return GNUNET_OK;
171 }
172
173 /**
174  * Process sensordashboard requests.
175  *
176  * @param cls closure
177  * @param server the initialized server
178  * @param cfg configuration to use
179  */
180 static void
181 run (void *cls, struct GNUNET_SERVER_Handle *server,
182      const struct GNUNET_CONFIGURATION_Handle *cfg)
183 {
184   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
185     {NULL, NULL, 0, 0}
186   };
187   static struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
188       {&sensor_reading_receiver, GNUNET_MESSAGE_TYPE_SENSOR_READING, 0},
189       {NULL, 0, 0}
190   };
191   static uint32_t cadet_ports[] = {
192       GNUNET_APPLICATION_TYPE_SENSORDASHBOARD,
193       GNUNET_APPLICATION_TYPE_END
194   };
195   sensors = GNUNET_SENSOR_load_all_sensors ();
196   GNUNET_assert (NULL != sensors);
197   cadet = GNUNET_CADET_connect(cfg,
198       NULL,
199       &cadet_channel_created,
200       &cadet_channel_destroyed,
201       cadet_handlers,
202       cadet_ports);
203   if(NULL == cadet)
204   {
205     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
206         _("Failed to connect to `%s' service.\n"), "CADET");
207     GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
208     return;
209   }
210   peerstore = GNUNET_PEERSTORE_connect (cfg);
211   if (NULL == peerstore)
212   {
213     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
214         _("Failed to connect to `%s' service.\n"), "PEERSTORE");
215     GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
216     return;
217   }
218   GNUNET_SERVER_add_handlers (server, handlers);
219   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
220                                 NULL);
221 }
222
223
224 /**
225  * The main function for the sensordashboard service.
226  *
227  * @param argc number of arguments from the command line
228  * @param argv command line arguments
229  * @return 0 ok, 1 on error
230  */
231 int
232 main (int argc, char *const *argv)
233 {
234   return (GNUNET_OK ==
235           GNUNET_SERVICE_run (argc, argv, "sensordashboard",
236                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
237 }
238
239 /* end of gnunet-service-sensordashboard.c */