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