2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file sensordashboard/gnunet-service-sensordashboard.c
23 * @brief Service collecting sensor readings from peers
24 * @author Omar Tarabai
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"
37 * Context of a connected client peer
39 struct ClientPeerContext
45 struct ClientPeerContext *prev;
50 struct ClientPeerContext *next;
53 * GNUnet Peer identity
55 struct GNUNET_PeerIdentity peerid;
58 * Handle to the cadet channel
60 struct GNUNET_CADET_Channel *ch;
66 * Handle to CADET service
68 static struct GNUNET_CADET_Handle *cadet;
71 * Global hashmap of defined sensors
73 static struct GNUNET_CONTAINER_MultiHashMap *sensors;
76 * Handle to the peerstore service connection
78 static struct GNUNET_PEERSTORE_Handle *peerstore;
81 * Name of this subsystem to be used for peerstore operations
83 static char *subsystem = "sensordashboard";
86 * Head of a DLL of all connected client peers
88 static struct ClientPeerContext *cp_head;
91 * Tail of a DLL of all connected client peers
93 static struct ClientPeerContext *cp_tail;
97 * Destroy a given client peer context
99 * @param cp client peer context
102 destroy_clientpeer (struct ClientPeerContext *cp)
106 GNUNET_CADET_channel_destroy (cp->ch);
113 * Task run during shutdown.
119 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
121 struct ClientPeerContext *cp;
126 GNUNET_CONTAINER_DLL_remove (cp_head, cp_tail, cp);
127 destroy_clientpeer (cp);
132 GNUNET_CADET_disconnect (cadet);
135 if (NULL != peerstore)
137 GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_YES);
140 GNUNET_SENSOR_destroy_sensors (sensors);
141 GNUNET_SCHEDULER_shutdown();
145 * Function called whenever a channel is destroyed. Should clean up
146 * any associated state.
148 * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
150 * @param cls closure (set from #GNUNET_CADET_connect)
151 * @param channel connection to the other end (henceforth invalid)
152 * @param channel_ctx place where local state associated
153 * with the channel is stored
156 cadet_channel_destroyed (void *cls,
157 const struct GNUNET_CADET_Channel *channel,
160 struct ClientPeerContext *cp = channel_ctx;
163 GNUNET_CONTAINER_DLL_remove (cp_head, cp_tail, cp);
164 destroy_clientpeer (cp);
168 * Method called whenever another peer has added us to a channel
169 * the other peer initiated.
170 * Only called (once) upon reception of data with a message type which was
171 * subscribed to in #GNUNET_CADET_connect.
173 * A call to #GNUNET_CADET_channel_destroy causes the channel to be ignored. In
174 * this case the handler MUST return NULL.
177 * @param channel new handle to the channel
178 * @param initiator peer that started the channel
179 * @param port Port this channel is for.
180 * @param options CadetOption flag field, with all active option bits set to 1.
182 * @return initial channel context for the channel
183 * (can be NULL -- that's not an error)
186 cadet_channel_created (void *cls,
187 struct GNUNET_CADET_Channel *channel,
188 const struct GNUNET_PeerIdentity *initiator,
189 uint32_t port, enum GNUNET_CADET_ChannelOption options)
191 struct ClientPeerContext *cp;
193 cp = GNUNET_new (struct ClientPeerContext);
194 cp->peerid = *initiator;
196 GNUNET_CONTAINER_DLL_insert (cp_head, cp_tail, cp);
201 * Called with any sensor reading messages received from CADET.
203 * Each time the function must call #GNUNET_CADET_receive_done on the channel
204 * in order to receive the next message. This doesn't need to be immediate:
205 * can be delayed if some processing is done on the message.
207 * @param cls Closure (set from #GNUNET_CADET_connect).
208 * @param channel Connection to the other end.
209 * @param channel_ctx Place to store local state associated with the channel.
210 * @param message The actual message.
211 * @return #GNUNET_OK to keep the channel open,
212 * #GNUNET_SYSERR to close it (signal serious error).
215 handle_sensor_reading (void *cls,
216 struct GNUNET_CADET_Channel *channel,
218 const struct GNUNET_MessageHeader *message)
220 struct GNUNET_PeerIdentity *peer = *channel_ctx;
221 struct GNUNET_SENSOR_Reading *reading;
223 reading = GNUNET_SENSOR_parse_reading_message (message, sensors);
226 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
227 "Received an invalid sensor reading from peer `%s'\n",
229 return GNUNET_SYSERR;
231 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
232 "Received a sensor reading from peer `%s':\n"
233 "# Sensor name: `%s'\n"
234 "# Timestamp: %" PRIu64 "\n"
235 "# Value size: %" PRIu64 ".\n",
237 reading->sensor->name,
239 reading->value_size);
240 GNUNET_PEERSTORE_store (peerstore, subsystem, peer, reading->sensor->name,
241 reading->value, reading->value_size,
242 GNUNET_TIME_UNIT_FOREVER_ABS,
243 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, NULL, NULL);
244 GNUNET_free (reading->value);
245 GNUNET_free (reading);
246 GNUNET_CADET_receive_done (channel);
252 * Called with any sensor list request received.
254 * Each time the function must call #GNUNET_CADET_receive_done on the channel
255 * in order to receive the next message. This doesn't need to be immediate:
256 * can be delayed if some processing is done on the message.
258 * @param cls Closure (set from #GNUNET_CADET_connect).
259 * @param channel Connection to the other end.
260 * @param channel_ctx Place to store local state associated with the channel.
261 * @param message The actual message.
262 * @return #GNUNET_OK to keep the channel open,
263 * #GNUNET_SYSERR to close it (signal serious error).
266 handle_sensor_list_req (void *cls,
267 struct GNUNET_CADET_Channel *channel,
269 const struct GNUNET_MessageHeader *message)
272 GNUNET_CADET_receive_done (channel);
278 * Process sensordashboard requests.
281 * @param server the initialized server
282 * @param cfg configuration to use
285 run (void *cls, struct GNUNET_SERVER_Handle *server,
286 const struct GNUNET_CONFIGURATION_Handle *cfg)
288 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
291 static struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
292 {&handle_sensor_reading,
293 GNUNET_MESSAGE_TYPE_SENSOR_READING, 0},
294 {&handle_sensor_list_req,
295 GNUNET_MESSAGE_TYPE_SENSOR_LIST_REQ,
296 sizeof (struct GNUNET_MessageHeader)},
299 static uint32_t cadet_ports[] = {
300 GNUNET_APPLICATION_TYPE_SENSORDASHBOARD,
301 GNUNET_APPLICATION_TYPE_SENSORUPDATE,
302 GNUNET_APPLICATION_TYPE_END
304 sensors = GNUNET_SENSOR_load_all_sensors ();
305 GNUNET_assert (NULL != sensors);
306 cadet = GNUNET_CADET_connect(cfg,
308 &cadet_channel_created,
309 &cadet_channel_destroyed,
314 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
315 _("Failed to connect to `%s' service.\n"), "CADET");
316 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
319 peerstore = GNUNET_PEERSTORE_connect (cfg);
320 if (NULL == peerstore)
322 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
323 _("Failed to connect to `%s' service.\n"), "PEERSTORE");
324 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
327 GNUNET_SERVER_add_handlers (server, handlers);
328 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
334 * The main function for the sensordashboard service.
336 * @param argc number of arguments from the command line
337 * @param argv command line arguments
338 * @return 0 ok, 1 on error
341 main (int argc, char *const *argv)
344 GNUNET_SERVICE_run (argc, argv, "sensordashboard",
345 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
348 /* end of gnunet-service-sensordashboard.c */