aboutsummaryrefslogtreecommitdiff
path: root/src/sensor
diff options
context:
space:
mode:
authorOmar Tarabai <tarabai@devegypt.com>2014-04-14 12:08:48 +0000
committerOmar Tarabai <tarabai@devegypt.com>2014-04-14 12:08:48 +0000
commita3485503b228317cb7a9813a1049cb510384d577 (patch)
tree5606d74e66398b2596be873c03574dac6ce69866 /src/sensor
parent750b5dc4e16072de66931a8c17da8d95aba66fb7 (diff)
downloadgnunet-a3485503b228317cb7a9813a1049cb510384d577.tar.gz
gnunet-a3485503b228317cb7a9813a1049cb510384d577.zip
SENSOR component inital commit
Diffstat (limited to 'src/sensor')
-rw-r--r--src/sensor/Makefile.am69
-rw-r--r--src/sensor/gnunet-sensor.c149
-rw-r--r--src/sensor/gnunet-service-sensor.c577
-rw-r--r--src/sensor/sensor.conf.in7
-rw-r--r--src/sensor/sensor.h63
-rw-r--r--src/sensor/sensor_api.c627
-rw-r--r--src/sensor/test_sensor_api.c84
7 files changed, 1576 insertions, 0 deletions
diff --git a/src/sensor/Makefile.am b/src/sensor/Makefile.am
new file mode 100644
index 000000000..24479cff9
--- /dev/null
+++ b/src/sensor/Makefile.am
@@ -0,0 +1,69 @@
1SUBDIRS = .
2
3INCLUDES = \
4 -I$(top_srcdir)/src/include \
5 -I$(top_srcdir)
6
7AM_CPPFLAGS = \
8 $(GNUNET_CPPFLAGS)
9
10# Set this variable if you are using GNUNET libraries for all programs and
11# libraries. You don't then need to target-specific _LDFLAGS with GNUNET_LDFLAGS
12# AM_LDFLAGS = \
13# $(GNUNET_LDFLAGS) \
14# $(WINFLAGS) \
15# -export-dynamic
16
17lib_LTLIBRARIES = libgnunetsensor.la
18
19pkgcfgdir= $(prefix)/share/gnunet/config.d/
20
21libexecdir= $(prefix)/lib/gnunet/libexec/
22
23libgnunetsensor_la_SOURCES = \
24 sensor_api.c
25libgnunetsensor_la_LIBADD = \
26 -lgnunetutil
27libgnunetsensor_la_LDFLAGS = \
28 $(GNUNET_LDFLAGS) $(WINFLAGS) \
29 -version-info 0:0:0
30
31
32bin_PROGRAMS = gnunet-sensor
33
34libexec_PROGRAMS = gnunet-service-sensor
35
36check_PROGRAMS = \
37 test_sensor_api
38
39TESTS = $(check_PROGRAMS)
40
41gnunet_service_sensor_SOURCES = \
42 gnunet-service-sensor.c
43gnunet_service_sensor_LDADD = \
44 -lgnunetutil -lgnunetcore -lgnunetdht\
45 $(INTLLIBS)
46gnunet_service_sensor_LDFLAGS = \
47 $(GNUNET_LDFLAGS) $(WINFLAGS) -export-dynamic
48
49gnunet_sensor_SOURCES = \
50 gnunet-sensor.c
51gnunet_sensor_LDADD = \
52 -lgnunetutil \
53 libgnunetsensor.la \
54 $(INTLLIBS)
55gnunet_sensor_LDFLAGS = \
56 $(GNUNET_LDFLAGS) $(WINFLAGS) -export-dynamic
57
58
59
60test_sensor_api_SOURCES = \
61 test_sensor_api.c
62test_sensor_api_LDADD = \
63 $(top_builddir)/src/sensor/libgnunetsensor.la \
64 -lgnunetutil
65test_sensor_api_LDFLAGS = \
66 $(GNUNET_LDFLAGS) $(WINFLAGS) -export-dynamic
67
68 pkgcfg_DATA = sensor.conf
69
diff --git a/src/sensor/gnunet-sensor.c b/src/sensor/gnunet-sensor.c
new file mode 100644
index 000000000..dd06d6e0b
--- /dev/null
+++ b/src/sensor/gnunet-sensor.c
@@ -0,0 +1,149 @@
1/*
2 This file is part of GNUnet.
3 (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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file sensor/gnunet-sensor.c
23 * @brief sensor tool
24 * @author Omar Tarabai
25 */
26#include <gnunet/platform.h>
27#include <gnunet/gnunet_util_lib.h>
28#include "gnunet_sensor_service.h"
29
30static int ret;
31
32/*
33 * option '-a'
34 */
35static int get_all;
36
37/*
38 * Handle to sensor service
39 */
40struct GNUNET_SENSOR_Handle *sensor_handle;
41
42/**
43 * Run on shutdown
44 *
45 * @param cls unused
46 * @param tc scheduler context
47 */
48static void
49shutdown_task (void *cls,
50 const struct GNUNET_SCHEDULER_TaskContext *tc)
51{
52 if(NULL != sensor_handle)
53 {
54 GNUNET_SENSOR_disconnect(sensor_handle);
55 sensor_handle = NULL;
56 }
57}
58
59/**
60 * Callback for getting sensor info from service
61 *
62 * @param cls not used
63 * @param sensor brief information about sensor (NULL means end of transmission)
64 * @param err_msg contains error string if any
65 */
66void print_sensor_info(void *cls,
67 const struct SensorInfoShort *sensor,
68 const char *err_msg)
69{
70 if(NULL != err_msg)
71 {
72 printf("Error: %s\n", err_msg);
73 GNUNET_SCHEDULER_shutdown();
74 return;
75 }
76 if(NULL == sensor) /* no more sensors from service */
77 {
78 GNUNET_SCHEDULER_shutdown();
79 return;
80 }
81 printf("Name: %s\nVersion: %d.%d\n",
82 sensor->name,
83 sensor->version_major,
84 sensor->version_minor);
85 if(NULL != sensor->description)
86 printf("Description: %s\n", sensor->description);
87 printf("\n");
88}
89
90/**
91 * Main function that will be run by the scheduler.
92 *
93 * @param cls closure
94 * @param args remaining command-line arguments
95 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
96 * @param cfg configuration
97 */
98static void
99run (void *cls,
100 char *const *args,
101 const char *cfgfile,
102 const struct GNUNET_CONFIGURATION_Handle *cfg)
103{
104
105 sensor_handle = NULL;
106 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
107 &shutdown_task,
108 NULL);
109 if(GNUNET_YES == get_all)
110 {
111 sensor_handle = GNUNET_SENSOR_connect(cfg);
112 GNUNET_assert(NULL != sensor_handle);
113 GNUNET_SENSOR_iterate_sensors(sensor_handle,
114 GNUNET_TIME_UNIT_FOREVER_REL,
115 NULL,
116 0,
117 &print_sensor_info,
118 NULL);
119 }
120
121 ret = 0;
122}
123
124/**
125 * The main function to sensor.
126 *
127 * @param argc number of arguments from the command line
128 * @param argv command line arguments
129 * @return 0 ok, 1 on error
130 */
131int
132main (int argc, char *const *argv)
133{
134 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
135 {'a', "all", NULL,
136 gettext_noop("Retrieve names of all defined sensors"),
137 0, &GNUNET_GETOPT_set_one, &get_all},
138 GNUNET_GETOPT_OPTION_END
139 };
140 return (GNUNET_OK ==
141 GNUNET_PROGRAM_run (argc,
142 argv,
143 "gnunet-sensor [options [value]]",
144 gettext_noop
145 ("sensor"),
146 options, &run, NULL)) ? ret : 1;
147}
148
149/* end of gnunet-sensor.c */
diff --git a/src/sensor/gnunet-service-sensor.c b/src/sensor/gnunet-service-sensor.c
new file mode 100644
index 000000000..28c608e94
--- /dev/null
+++ b/src/sensor/gnunet-service-sensor.c
@@ -0,0 +1,577 @@
1/*
2 This file is part of GNUnet.
3 (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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file sensor/gnunet-service-sensor.c
23 * @brief sensor service implementation
24 * @author Christian Grothoff
25 */
26#include <gnunet/platform.h>
27#include <gnunet/gnunet_util_lib.h>
28#include "sensor.h"
29
30/**
31 * Structure containing sensor definition
32 */
33struct SensorInfo
34{
35
36 /*
37 * Sensor name
38 */
39 char *name;
40
41 /*
42 * Path to definition file
43 */
44 char *def_file;
45
46 /*
47 * First part of version number
48 */
49 uint16_t version_major;
50
51 /*
52 * Second part of version number
53 */
54 uint16_t version_minor;
55
56 /*
57 * Sensor description
58 */
59 char *description;
60
61 /*
62 * Category under which the sensor falls (e.g. tcp, datastore)
63 */
64 char *category;
65
66 /*
67 * When does the sensor become active
68 */
69 struct GNUNET_TIME_Absolute *start_time;
70
71 /*
72 * When does the sensor expire
73 */
74 struct GNUNET_TIME_Absolute *end_time;
75
76 /*
77 * Time interval to collect sensor information (e.g. every 1 min)
78 */
79 struct GNUNET_TIME_Relative *interval;
80
81 /*
82 * Lifetime of an information sample after which it is deleted from storage
83 */
84 struct GNUNET_TIME_Relative *lifetime;
85
86 /*
87 * A set of required peer capabilities for the sensor to collect meaningful information (e.g. ipv6)
88 */
89 char *capabilities;
90
91 /*
92 * Either "gnunet-statistics" or external "process"
93 */
94 char *source;
95
96 /*
97 * Name of the GNUnet service that is the source for the gnunet-statistics entry
98 */
99 char *gnunet_stat_service;
100
101 /*
102 * Name of the gnunet-statistics entry
103 */
104 char *gnunet_stat_name;
105
106 /*
107 * Name of the external process to be executed
108 */
109 char *ext_process;
110
111 /*
112 * Arguments to be passed to the external process
113 */
114 char *ext_args;
115
116 /*
117 * The output datatype to be expected
118 */
119 char *expected_datatype;
120
121 /*
122 * Peer-identity of peer running collection point
123 */
124 struct GNUNET_PeerIdentity *collection_point;
125
126 /*
127 * Time interval to send sensor information to collection point (e.g. every 30 mins)
128 */
129 struct GNUNET_TIME_Relative *collection_interval;
130
131 /*
132 * Flag specifying if value is to be communicated to the p2p network
133 */
134 int p2p_report;
135
136 /*
137 * Time interval to communicate value to the p2p network
138 */
139 struct GNUNET_TIME_Relative *p2p_interval;
140
141};
142
143/**
144 * Our configuration.
145 */
146static const struct GNUNET_CONFIGURATION_Handle *cfg;
147
148/**
149 * Hashmap of loaded sensor definitions
150 */
151struct GNUNET_CONTAINER_MultiHashMap *sensors;
152
153/**
154 * Task run during shutdown.
155 *
156 * @param cls unused
157 * @param tc unused
158 */
159static void
160shutdown_task (void *cls,
161 const struct GNUNET_SCHEDULER_TaskContext *tc)
162{
163}
164
165
166/**
167 * A client disconnected. Remove all of its data structure entries.
168 *
169 * @param cls closure, NULL
170 * @param client identification of the client
171 */
172static void
173handle_client_disconnect (void *cls,
174 struct GNUNET_SERVER_Client
175 * client)
176{
177}
178
179/**
180 * Parses a version number string into major and minor
181 *
182 * @param version full version string
183 * @param major pointer to parsed major value
184 * @param minor pointer to parsed minor value
185 * @return #GNUNET_OK if parsing went ok, #GNUNET_SYSERROR in case of error
186 */
187static int
188version_parse(char *version, uint16_t *major, uint16_t *minor)
189{
190 int majorval = 0;
191 int minorval = 0;
192
193 for(; isdigit(*version); version++)
194 {
195 majorval *= 10;
196 majorval += *version - '0';
197 }
198 if(*version != '.')
199 return GNUNET_SYSERR;
200 version++;
201 for(; isdigit(*version); version++)
202 {
203 minorval *= 10;
204 minorval += *version - '0';
205 }
206 if(*version != 0)
207 return GNUNET_SYSERR;
208 *major = majorval;
209 *minor = minorval;
210
211 return GNUNET_OK;
212}
213
214/**
215 * Load sensor definition from configuration
216 *
217 * @param cfg configuration handle
218 * @param sectionname configuration section containing definition
219 */
220static struct SensorInfo *
221load_sensor_from_cfg(struct GNUNET_CONFIGURATION_Handle *cfg, char *sectionname)
222{
223 struct SensorInfo *sensor;
224 char *versionstr;
225
226 sensor = GNUNET_new(struct SensorInfo);
227 //name
228 sensor->name = GNUNET_strdup(sectionname);
229 //version
230 if(GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, sectionname, "VERSION", &versionstr) ||
231 NULL == versionstr)
232 {
233 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Error reading sensor version\n"));
234 GNUNET_free(sensor);
235 return NULL;
236 }
237 if(GNUNET_OK != version_parse(versionstr, &(sensor->version_major), &(sensor->version_minor)))
238 {
239 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Invalid sensor version number, format should be major.minor\n"));
240 GNUNET_free(sensor);
241 return NULL;
242 }
243 //description
244 GNUNET_CONFIGURATION_get_value_string(cfg, sectionname, "DESCRIPTION", &sensor->description);
245 //category
246 if(GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, sectionname, "CATEGORY", &sensor->category) ||
247 NULL == sensor->category)
248 {
249 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Error reading sensor category\n"));
250 GNUNET_free(sensor);
251 return NULL;
252 }
253
254 return sensor;
255}
256
257/**
258 * Load sensor definition from file
259 *
260 * @param filename full path to file containing sensor definition
261 */
262static struct SensorInfo *
263load_sensor_from_file(const char *filename)
264{
265 struct GNUNET_CONFIGURATION_Handle *sensorcfg;
266 char *filebasename;
267 struct SensorInfo *sensor;
268
269 //test file
270 if(GNUNET_YES != GNUNET_DISK_file_test(filename))
271 {
272 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to access sensor file: %s\n"), filename);
273 return NULL;
274 }
275 //load file as configuration
276 sensorcfg = GNUNET_CONFIGURATION_create();
277 if(GNUNET_SYSERR == GNUNET_CONFIGURATION_parse(sensorcfg, filename))
278 {
279 GNUNET_CONFIGURATION_destroy(sensorcfg);
280 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to load sensor definition: %s\n"), filename);
281 return NULL;
282 }
283 //configuration section should be the same as filename
284 filebasename = GNUNET_STRINGS_get_short_name(filename);
285 sensor = load_sensor_from_cfg(sensorcfg, filebasename);
286 sensor->def_file = GNUNET_strdup(filename);
287
288 GNUNET_CONFIGURATION_destroy(sensorcfg);
289
290 return sensor;
291}
292
293/**
294 * Compares version numbers of two sensors
295 *
296 * @param s1 first sensor
297 * @param s2 second sensor
298 * @return 1: s1 > s2, 0: s1 == s2, -1: s1 < s2
299 */
300static int
301sensor_version_compare(struct SensorInfo *s1, struct SensorInfo *s2)
302{
303 if(s1->version_major == s2->version_major)
304 return (s1->version_minor < s2->version_minor) ? -1 : (s1->version_minor > s2->version_minor);
305 else
306 return (s1->version_major < s2->version_major) ? -1 : (s1->version_major > s2->version_major);
307}
308
309/**
310 * Adds a new sensor to given hashmap.
311 * If the same name exist, compares versions and update if old.
312 *
313 * @param sensor Sensor structure to add
314 * @param map Hashmap to add to
315 * @return #GNUNET_YES if added, #GNUNET_NO if not added which is not necessarily an error
316 */
317static int
318add_sensor_to_hashmap(struct SensorInfo *sensor, struct GNUNET_CONTAINER_MultiHashMap *map)
319{
320 struct GNUNET_HashCode key;
321 struct SensorInfo *existing;
322
323 GNUNET_CRYPTO_hash(sensor->name, sizeof(sensor->name), &key);
324 existing = GNUNET_CONTAINER_multihashmap_get(map, &key);
325 if(NULL != existing) //sensor with same name already exists
326 {
327 if(sensor_version_compare(existing, sensor) >= 0) //same or newer version already exist
328 {
329 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Sensor `%s' already exists with same or newer version\n"), sensor->name);
330 return GNUNET_NO;
331 }
332 else
333 {
334 GNUNET_CONTAINER_multihashmap_remove(map, &key, existing); //remove the old version
335 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Upgrading sensor `%s' to a newer version\n"), sensor->name);
336 }
337 }
338 if(GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put(map, &key, sensor, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
339 {
340 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Error adding new sensor `%s' to global hashmap, this should not happen\n"), sensor->name);
341 return GNUNET_NO;
342 }
343
344 return GNUNET_YES;
345}
346
347/**
348 * Iterating over files in sensors directory
349 *
350 * @param cls closure
351 * @param filename complete filename (absolute path)
352 * @return #GNUNET_OK to continue to iterate,
353 * #GNUNET_NO to stop iteration with no error,
354 * #GNUNET_SYSERR to abort iteration with error!
355 */
356static int
357reload_sensors_dir_cb(void *cls, const char *filename)
358{
359 struct SensorInfo *sensor;
360
361 sensor = load_sensor_from_file(filename);
362 if(NULL == sensor)
363 {
364 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Error loading sensor from file: %s\n"), filename);
365 return GNUNET_OK;
366 }
367 if(GNUNET_YES == add_sensor_to_hashmap(sensor, sensors))
368 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Sensor `%s' added to global hashmap\n"), sensor->name);
369 else
370 GNUNET_log(GNUNET_ERROR_TYPE_INFO, ("Could not add sensor `%s' to global hashmap\n"), sensor->name);
371
372 return GNUNET_OK;
373}
374
375/*
376 * Get path to the directory containing the sensor definition files
377 *
378 * @return sensor files directory
379 */
380static char *
381get_sensor_dir()
382{
383 char* datadir;
384 char* sensordir;
385
386 datadir = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_SELF_PREFIX);
387 //should eval to '$prefix/share/gnunet-mi/sensors/'
388 //TODO: is there a better way?
389 GNUNET_asprintf(&sensordir, "%sshare%sgnunet-mi%ssensors%s",
390 datadir, DIR_SEPARATOR_STR, DIR_SEPARATOR_STR, DIR_SEPARATOR_STR);
391
392 return sensordir;
393}
394
395/**
396 * Reads sensor definitions from data files
397 *
398 */
399static void
400reload_sensors()
401{
402 char* sensordir;
403 int filesfound;
404
405 sensordir = get_sensor_dir();
406 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Reloading sensor definitions from directory `%s'\n"), sensordir);
407 GNUNET_assert(GNUNET_YES == GNUNET_DISK_directory_test(sensordir, GNUNET_YES));
408
409 //read all files in sensors directory
410 filesfound = GNUNET_DISK_directory_scan(sensordir, &reload_sensors_dir_cb, NULL);
411 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Loaded %d/%d sensors from directory `%s'\n"),
412 GNUNET_CONTAINER_multihashmap_size(sensors), filesfound, sensordir);
413}
414
415/**
416 * Creates a structure with basic sensor info to be sent to a client
417 *
418 * @parm sensor sensor information
419 * @return message ready to be sent to client
420 */
421static struct SensorInfoMessage *
422create_sensor_info_msg(struct SensorInfo *sensor)
423{
424 struct SensorInfoMessage *msg;
425 uint16_t len;
426 size_t name_len;
427 size_t desc_len;
428
429 name_len = strlen(sensor->name);
430 if(NULL == sensor->description)
431 desc_len = 0;
432 else
433 desc_len = strlen(sensor->description);
434 len = 0;
435 len += sizeof(struct SensorInfoMessage);
436 len += name_len;
437 len += desc_len;
438 msg = GNUNET_malloc(len);
439 msg->header.size = htons(len);
440 msg->header.type = htons(GNUNET_MESSAGE_TYPE_SENSOR_INFO);
441 msg->name_len = htons(name_len);
442 msg->description_len = htons(desc_len);
443 msg->version_major = htons(sensor->version_major);
444 msg->version_minor = htons(sensor->version_minor);
445 memcpy(&msg[1], sensor->name, name_len);
446 memcpy((&msg[1]) + name_len, sensor->description, desc_len);
447
448 return msg;
449}
450
451/**
452 * Handle GET SENSOR message.
453 *
454 * @param cls closure
455 * @param client identification of the client
456 * @param message the actual message
457 */
458static void
459handle_get_sensor (void *cls, struct GNUNET_SERVER_Client *client,
460 const struct GNUNET_MessageHeader *message)
461{
462 struct GNUNET_SERVER_TransmitContext *tc;
463 char *sensorname;
464 size_t sensorname_len;
465 struct GNUNET_HashCode key;
466 struct SensorInfo *sensorinfo;
467 struct SensorInfoMessage *msg;
468
469 sensorname = (char *)&message[1];
470 sensorname_len = message->size - sizeof(struct GNUNET_MessageHeader);
471 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "`%s' message received for sensor `%.*s\n",
472 "GET SENSOR", sensorname_len, sensorname);
473 tc = GNUNET_SERVER_transmit_context_create (client);
474 GNUNET_CRYPTO_hash(sensorname, sensorname_len, &key);
475 sensorinfo = (struct SensorInfo *)GNUNET_CONTAINER_multihashmap_get(sensors, &key);
476 msg = create_sensor_info_msg(sensorinfo);
477 GNUNET_SERVER_transmit_context_append_message(tc, (struct GNUNET_MessageHeader *)msg);
478 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
479
480 GNUNET_free(msg);
481}
482
483/**
484 * Iterator for sensors and adds them to transmit context
485 *
486 * @param cls a 'struct GNUNET_SERVER_TransmitContext *'
487 * @param key hash of sensor name, key to hashmap
488 * @param value a 'struct SensorInfo *'
489 */
490int add_sensor_to_tc(void *cls,
491 const struct GNUNET_HashCode *key, void *value)
492{
493 struct GNUNET_SERVER_TransmitContext *tc = cls;
494 struct SensorInfo *sensorinfo = value;
495 struct SensorInfoMessage *msg;
496
497 msg = create_sensor_info_msg(sensorinfo);
498 GNUNET_SERVER_transmit_context_append_message(tc, (struct GNUNET_MessageHeader *)msg);
499
500 GNUNET_free(msg);
501
502 return GNUNET_YES;
503}
504
505/**
506 * Handle GET ALL SENSORS message.
507 *
508 * @param cls closure
509 * @param client identification of the client
510 * @param message the actual message
511 */
512static void
513handle_get_all_sensors (void *cls, struct GNUNET_SERVER_Client *client,
514 const struct GNUNET_MessageHeader *message)
515{
516 struct GNUNET_SERVER_TransmitContext *tc;
517
518 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "`%s' message received.\n",
519 "GET ALL SENSOR");
520 tc = GNUNET_SERVER_transmit_context_create (client);
521 GNUNET_CONTAINER_multihashmap_iterate(sensors, &add_sensor_to_tc, tc);
522 GNUNET_SERVER_transmit_context_append_data(tc, NULL, 0, GNUNET_MESSAGE_TYPE_SENSOR_END);
523 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
524}
525
526/**
527 * Process statistics requests.
528 *
529 * @param cls closure
530 * @param server the initialized server
531 * @param c configuration to use
532 */
533static void
534run (void *cls,
535 struct GNUNET_SERVER_Handle *server,
536 const struct GNUNET_CONFIGURATION_Handle *c)
537{
538 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
539 {&handle_get_sensor, NULL, GNUNET_MESSAGE_TYPE_SENSOR_GET,
540 sizeof (struct GNUNET_MessageHeader)},
541 {&handle_get_all_sensors, NULL, GNUNET_MESSAGE_TYPE_SENSOR_GETALL,
542 0},
543 {NULL, NULL, 0, 0}
544 };
545
546 cfg = c;
547 sensors = GNUNET_CONTAINER_multihashmap_create(10, GNUNET_NO);
548 reload_sensors();
549 GNUNET_SERVER_add_handlers (server, handlers);
550 GNUNET_SERVER_disconnect_notify (server,
551 &handle_client_disconnect,
552 NULL);
553 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
554 &shutdown_task,
555 NULL);
556}
557
558
559/**
560 * The main function for the sensor service.
561 *
562 * @param argc number of arguments from the command line
563 * @param argv command line arguments
564 * @return 0 ok, 1 on error
565 */
566int
567main (int argc, char *const *argv)
568{
569 return (GNUNET_OK ==
570 GNUNET_SERVICE_run (argc,
571 argv,
572 "sensor",
573 GNUNET_SERVICE_OPTION_NONE,
574 &run, NULL)) ? 0 : 1;
575}
576
577/* end of gnunet-service-sensor.c */
diff --git a/src/sensor/sensor.conf.in b/src/sensor/sensor.conf.in
new file mode 100644
index 000000000..c1978ef8d
--- /dev/null
+++ b/src/sensor/sensor.conf.in
@@ -0,0 +1,7 @@
1[sensor]
2BINARY = gnunet-service-sensor
3UNIXPATH = /tmp/gnunet-service-sensor.sock
4HOME = $SERVICEHOME
5# PORT = 2106
6@UNIXONLY@ PORT = 2087
7
diff --git a/src/sensor/sensor.h b/src/sensor/sensor.h
new file mode 100644
index 000000000..014eb5214
--- /dev/null
+++ b/src/sensor/sensor.h
@@ -0,0 +1,63 @@
1/*
2 This file is part of GNUnet
3 (C) 2012-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 * @file sensor/sensor.h
22 * @brief example IPC messages between SENSOR API and GNS service
23 * @author Omar Tarabai
24 */
25
26#include "gnunet_sensor_service.h"
27
28
29GNUNET_NETWORK_STRUCT_BEGIN
30
31/**
32 * Carries a summary of a sensor
33 *
34 */
35struct SensorInfoMessage
36{
37 /**
38 * Message header
39 */
40 struct GNUNET_MessageHeader header;
41
42 /**
43 * Length of sensor name (name follows the struct)
44 */
45 size_t name_len;
46
47 /**
48 * First part of version number
49 */
50 uint16_t version_major;
51
52 /**
53 * Second part of version number
54 */
55 uint16_t version_minor;
56
57 /**
58 * Length of sensor description (description itself follows)
59 */
60 size_t description_len;
61};
62
63GNUNET_NETWORK_STRUCT_END
diff --git a/src/sensor/sensor_api.c b/src/sensor/sensor_api.c
new file mode 100644
index 000000000..19ead13b3
--- /dev/null
+++ b/src/sensor/sensor_api.c
@@ -0,0 +1,627 @@
1/*
2 This file is part of GNUnet.
3 (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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file sensor/sensor_api.c
23 * @brief API for sensor
24 * @author Omar Tarabai
25 */
26#include <gnunet/platform.h>
27#include <gnunet/gnunet_util_lib.h>
28#include "sensor.h"
29
30#define LOG(kind,...) GNUNET_log_from (kind, "sensor-api",__VA_ARGS__)
31
32/******************************************************************************/
33/************************ DATA STRUCTURES ****************************/
34/******************************************************************************/
35
36/**
37 * Handle to the sensor service.
38 */
39struct GNUNET_SENSOR_Handle
40{
41
42 /**
43 * Our configuration.
44 */
45 const struct GNUNET_CONFIGURATION_Handle *cfg;
46
47 /**
48 * Connection to the service.
49 */
50 struct GNUNET_CLIENT_Connection *client;
51
52 /**
53 * Head of transmission queue.
54 */
55 struct GNUNET_SENSOR_RequestContext *rc_head;
56
57 /**
58 * Tail of transmission queue.
59 */
60 struct GNUNET_SENSOR_RequestContext *rc_tail;
61
62 /**
63 * Handle for the current transmission request, or NULL if none is pending.
64 */
65 struct GNUNET_CLIENT_TransmitHandle *th;
66
67 /**
68 * Head of iterator DLL.
69 */
70 struct GNUNET_SENSOR_SensorIteratorContext *ic_head;
71
72 /**
73 * Tail of iterator DLL.
74 */
75 struct GNUNET_SENSOR_SensorIteratorContext *ic_tail;
76
77 /**
78 * ID for a reconnect task.
79 */
80 GNUNET_SCHEDULER_TaskIdentifier r_task;
81
82 /**
83 * Are we now receiving?
84 */
85 int in_receive;
86
87};
88
89/**
90 * Entry in the transmission queue to SENSOR service.
91 *
92 */
93struct GNUNET_SENSOR_RequestContext
94{
95 /**
96 * This is a linked list.
97 */
98 struct GNUNET_SENSOR_RequestContext *next;
99
100 /**
101 * This is a linked list.
102 */
103 struct GNUNET_SENSOR_RequestContext *prev;
104
105 /**
106 * Handle to the SENSOR service.
107 */
108 struct GNUNET_SENSOR_Handle *h;
109
110 /**
111 * Function to call after request has been transmitted, or NULL.
112 */
113 GNUNET_SENSOR_Continuation cont;
114
115 /**
116 * Closure for 'cont'.
117 */
118 void *cont_cls;
119
120 /**
121 * Number of bytes of the request message (follows after this struct).
122 */
123 size_t size;
124
125};
126
127/**
128 * Context for an iteration request.
129 */
130struct GNUNET_SENSOR_SensorIteratorContext
131{
132
133 /**
134 * Kept in a DLL.
135 */
136 struct GNUNET_SENSOR_SensorIteratorContext *next;
137
138 /**
139 * Kept in a DLL.
140 */
141 struct GNUNET_SENSOR_SensorIteratorContext *prev;
142
143 /**
144 * Handle to the SENSOR service.
145 */
146 struct GNUNET_SENSOR_Handle *h;
147
148 /**
149 * Function to call with the results.
150 */
151 GNUNET_SENSOR_SensorIteratorCB callback;
152
153 /**
154 * Closure for 'callback'.
155 */
156 void *callback_cls;
157
158 /**
159 * Our entry in the transmission queue.
160 */
161 struct GNUNET_SENSOR_RequestContext *rc;
162
163 /**
164 * Task responsible for timeout.
165 */
166 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
167
168 /**
169 * Timeout for the operation.
170 */
171 struct GNUNET_TIME_Absolute timeout;
172
173 /**
174 * Set to GNUNET_YES if we are currently receiving replies from the
175 * service.
176 */
177 int request_transmitted;
178
179};
180
181/******************************************************************************/
182/*********************** DECLARATIONS *************************/
183/******************************************************************************/
184
185/**
186 * Close the existing connection to SENSOR and reconnect.
187 *
188 * @param h handle to the service
189 */
190static void
191reconnect (struct GNUNET_SENSOR_Handle *h);
192
193/**
194 * Check if we have a request pending in the transmission queue and are
195 * able to transmit it right now. If so, schedule transmission.
196 *
197 * @param h handle to the service
198 */
199static void
200trigger_transmit (struct GNUNET_SENSOR_Handle *h);
201
202/******************************************************************************/
203/******************* CONNECTION FUNCTIONS *********************/
204/******************************************************************************/
205
206/**
207 * Connect to the sensor service.
208 *
209 * @return NULL on error
210 */
211struct GNUNET_SENSOR_Handle *
212GNUNET_SENSOR_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
213{
214 struct GNUNET_CLIENT_Connection *client;
215 struct GNUNET_SENSOR_Handle *h;
216
217 client = GNUNET_CLIENT_connect ("sensor", cfg);
218 if(NULL == client)
219 return NULL;
220 h = GNUNET_new (struct GNUNET_SENSOR_Handle);
221 h->client = client;
222 h->cfg = cfg;
223 return h;
224}
225
226/**
227 * Disconnect from the sensor service
228 *
229 * @param h handle to disconnect
230 */
231void
232GNUNET_SENSOR_disconnect(struct GNUNET_SENSOR_Handle *h)
233{
234 if (NULL != h->client)
235 {
236 GNUNET_CLIENT_disconnect (h->client);
237 h->client = NULL;
238 }
239 GNUNET_free (h);
240}
241
242/**
243 * Task scheduled to re-try connecting to the sensor service.
244 *
245 * @param cls the 'struct GNUNET_SENSOR_Handle'
246 * @param tc scheduler context
247 */
248static void
249reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
250{
251 struct GNUNET_SENSOR_Handle *h = cls;
252
253 h->r_task = GNUNET_SCHEDULER_NO_TASK;
254 reconnect (h);
255}
256
257/**
258 * Close the existing connection to SENSOR and reconnect.
259 *
260 * @param h handle to the service
261 */
262static void
263reconnect (struct GNUNET_SENSOR_Handle *h)
264{
265 if (GNUNET_SCHEDULER_NO_TASK != h->r_task)
266 {
267 GNUNET_SCHEDULER_cancel (h->r_task);
268 h->r_task = GNUNET_SCHEDULER_NO_TASK;
269 }
270 if (NULL != h->th)
271 {
272 GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
273 h->th = NULL;
274 }
275 if (NULL != h->client)
276 {
277 GNUNET_CLIENT_disconnect (h->client);
278 h->client = NULL;
279 }
280 h->in_receive = GNUNET_NO;
281 h->client = GNUNET_CLIENT_connect ("sensor", h->cfg);
282 if (NULL == h->client)
283 {
284 h->r_task =
285 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task,
286 h);
287 return;
288 }
289 trigger_transmit (h);
290}
291
292/******************************************************************************/
293/****************** SENSOR DATA FUNCTIONS *********************/
294/******************************************************************************/
295
296/**
297 * Cancel an iteration over sensor information.
298 *
299 * @param ic context of the iterator to cancel
300 */
301void
302GNUNET_SENSOR_iterate_sensor_cancel (struct GNUNET_SENSOR_SensorIteratorContext *ic)
303{
304 struct GNUNET_SENSOR_Handle *h;
305
306 h = ic->h;
307 if (GNUNET_SCHEDULER_NO_TASK != ic->timeout_task)
308 {
309 GNUNET_SCHEDULER_cancel (ic->timeout_task);
310 ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
311 }
312 ic->callback = NULL;
313 if (GNUNET_YES == ic->request_transmitted)
314 return; /* need to finish processing */
315 GNUNET_CONTAINER_DLL_remove (h->ic_head,
316 h->ic_tail,
317 ic);
318 if (NULL != ic->rc)
319 {
320 GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, ic->rc);
321 GNUNET_free (ic->rc);
322 }
323 GNUNET_free (ic);
324}
325
326/**
327 * Iteration request has timed out.
328 *
329 * @param cls the 'struct GNUNET_SENSOR_SensorIteratorContext*'
330 * @param tc scheduler context
331 */
332static void
333signal_sensor_iteration_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
334{
335 struct GNUNET_SENSOR_SensorIteratorContext *ic = cls;
336 GNUNET_SENSOR_SensorIteratorCB cb;
337 void *cb_cls;
338
339 ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
340 cb = ic->callback;
341 cb_cls = ic->callback_cls;
342 GNUNET_SENSOR_iterate_sensor_cancel (ic);
343 if (NULL != cb)
344 cb (cb_cls, NULL,
345 _("Timeout transmitting iteration request to `SENSOR' service."));
346}
347
348/**
349 * Type of a function to call when we receive a message from the
350 * service. Call the iterator with the result and (if applicable)
351 * continue to receive more messages or trigger processing the next
352 * event (if applicable).
353 *
354 * @param cls closure
355 * @param msg message received, NULL on timeout or fatal error
356 */
357static void
358sensor_handler(void *cls, const struct GNUNET_MessageHeader *msg)
359{
360 struct GNUNET_SENSOR_Handle *h = cls;
361 struct GNUNET_SENSOR_SensorIteratorContext *ic = h->ic_head;
362 GNUNET_SENSOR_SensorIteratorCB cb;
363 void *cb_cls;
364 uint16_t ms;
365 const struct SensorInfoMessage *im;
366 struct SensorInfoShort *sensor;
367 size_t name_len;
368 size_t desc_len;
369
370
371 h->in_receive = GNUNET_NO;
372 if (NULL == msg)
373 {
374 /* sensor service died, signal error */
375 if (NULL != ic)
376 {
377 cb = ic->callback;
378 cb_cls = ic->callback_cls;
379 GNUNET_SENSOR_iterate_sensor_cancel(ic);
380 }
381 else
382 {
383 cb = NULL;
384 }
385 reconnect (h);
386 if (NULL != cb)
387 cb (cb_cls, NULL,
388 _("Failed to receive response from `SENSOR' service."));
389 return;
390 }
391 if (NULL == ic)
392 {
393 /* didn't expect a response, reconnect */
394 reconnect (h);
395 return;
396 }
397 ic->request_transmitted = GNUNET_NO;
398 cb = ic->callback;
399 cb_cls = ic->callback_cls;
400 if (GNUNET_MESSAGE_TYPE_SENSOR_END == ntohs (msg->type))
401 {
402 /* normal end of list of sensors, signal end, process next pending request */
403 LOG (GNUNET_ERROR_TYPE_INFO,
404 "Received end of list of sensors from `%s' service\n", "SENSOR");
405 GNUNET_SENSOR_iterate_sensor_cancel(ic);
406 trigger_transmit (h);
407 if ( (GNUNET_NO == h->in_receive) &&
408 (NULL != h->ic_head) )
409 {
410 h->in_receive = GNUNET_YES;
411 GNUNET_CLIENT_receive (h->client, &sensor_handler, h,
412 GNUNET_TIME_absolute_get_remaining (h->ic_head->timeout));
413 }
414 if (NULL != cb)
415 cb (cb_cls, NULL, NULL);
416 return;
417 }
418 ms = ntohs (msg->size);
419 im = (const struct SensorInfoMessage *) msg;
420 name_len = ntohs(im->name_len);
421 desc_len = ntohs(im->description_len);
422 if ((ms != sizeof (struct SensorInfoMessage) + name_len + desc_len) ||
423 (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_SENSOR_INFO))
424 {
425 /* malformed message */
426 GNUNET_break (0);
427 GNUNET_SENSOR_iterate_sensor_cancel(ic);
428 reconnect (h);
429 if (NULL != cb)
430 cb (cb_cls, NULL,
431 _("Received invalid message from `SENSOR' service."));
432 return;
433 }
434 sensor = GNUNET_new(struct SensorInfoShort);
435 sensor->name = GNUNET_strndup((char *)&im[1], name_len);
436 if(desc_len > 0)
437 sensor->description = GNUNET_strndup((char *)((&im[1]) + name_len), desc_len);
438 sensor->version_major = ntohs(im->version_major);
439 sensor->version_minor = ntohs(im->version_minor);
440 h->in_receive = GNUNET_YES;
441 GNUNET_CLIENT_receive (h->client, &sensor_handler, h,
442 GNUNET_TIME_absolute_get_remaining (ic->timeout));
443 if (NULL != cb)
444 cb (cb_cls, sensor, NULL);
445}
446
447/**
448 * We've transmitted the iteration request. Now get ready to process
449 * the results (or handle transmission error).
450 *
451 * @param cls the 'struct GNUNET_SENSOR_SensorIteratorContext'
452 * @param emsg error message, NULL if transmission worked
453 */
454static void
455sensor_iterator_start_receive (void *cls, const char *emsg)
456{
457 struct GNUNET_SENSOR_SensorIteratorContext *ic = cls;
458 struct GNUNET_SENSOR_Handle *h = ic->h;
459 GNUNET_SENSOR_SensorIteratorCB cb;
460 void *cb_cls;
461
462 ic->rc = NULL;
463 if (NULL != emsg)
464 {
465 cb = ic->callback;
466 cb_cls = ic->callback_cls;
467 GNUNET_SENSOR_iterate_sensor_cancel (ic);
468 reconnect (h);
469 if (NULL != cb)
470 cb (cb_cls, NULL, emsg);
471 return;
472 }
473 LOG (GNUNET_ERROR_TYPE_DEBUG, "Waiting for response from `%s' service.\n",
474 "SENSOR");
475 ic->request_transmitted = GNUNET_YES;
476 if (GNUNET_NO == h->in_receive)
477 {
478 h->in_receive = GNUNET_YES;
479 GNUNET_CLIENT_receive (h->client, &sensor_handler, h,
480 GNUNET_TIME_absolute_get_remaining (ic->timeout));
481 }
482}
483
484/**
485 * Transmit the request at the head of the transmission queue
486 * and trigger continuation (if any).
487 *
488 * @param cls the 'struct GNUNET_SENSOR_Handle' (with the queue)
489 * @param size size of the buffer (0 on error)
490 * @param buf where to copy the message
491 * @return number of bytes copied to buf
492 */
493static size_t
494do_transmit (void *cls, size_t size, void *buf)
495{
496 struct GNUNET_SENSOR_Handle *h = cls;
497 struct GNUNET_SENSOR_RequestContext *rc = h->rc_head;
498 size_t ret;
499
500 h->th = NULL;
501 if (NULL == rc)
502 return 0; /* request was cancelled in the meantime */
503 if (NULL == buf)
504 {
505 /* sensor service died */
506 LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
507 "Failed to transmit message to `%s' service.\n", "SENSOR");
508 GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, rc);
509 reconnect (h);
510 if (NULL != rc->cont)
511 rc->cont (rc->cont_cls, _("failed to transmit request (service down?)"));
512 GNUNET_free (rc);
513 return 0;
514 }
515 ret = rc->size;
516 if (size < ret)
517 {
518 /* change in head of queue (i.e. cancel + add), try again */
519 trigger_transmit (h);
520 return 0;
521 }
522 LOG (GNUNET_ERROR_TYPE_DEBUG,
523 "Transmitting request of size %u to `%s' service.\n", ret, "SENSOR");
524 memcpy (buf, &rc[1], ret);
525 GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, rc);
526 trigger_transmit (h);
527 if (NULL != rc->cont)
528 rc->cont (rc->cont_cls, NULL);
529 GNUNET_free (rc);
530 return ret;
531}
532
533/**
534 * Check if we have a request pending in the transmission queue and are
535 * able to transmit it right now. If so, schedule transmission.
536 *
537 * @param h handle to the service
538 */
539static void
540trigger_transmit (struct GNUNET_SENSOR_Handle *h)
541{
542 struct GNUNET_SENSOR_RequestContext *rc;
543
544 if (NULL == (rc = h->rc_head))
545 return; /* no requests queued */
546 if (NULL != h->th)
547 return; /* request already pending */
548 if (NULL == h->client)
549 {
550 /* disconnected, try to reconnect */
551 reconnect (h);
552 return;
553 }
554 h->th =
555 GNUNET_CLIENT_notify_transmit_ready (h->client, rc->size,
556 GNUNET_TIME_UNIT_FOREVER_REL,
557 GNUNET_YES,
558 &do_transmit, h);
559}
560
561/**
562 * Client asking to iterate all available sensors
563 *
564 * @param h Handle to SENSOR service
565 * @param timeout how long to wait until timing out
566 * @param sensorname information on one sensor only, can be NULL to get all
567 * @param sensorname_len length of the sensorname parameter
568 * @param callback the method to call for each sensor
569 * @param callback_cls closure for callback
570 * @return iterator context
571 */
572struct GNUNET_SENSOR_SensorIteratorContext *
573GNUNET_SENSOR_iterate_sensors (struct GNUNET_SENSOR_Handle *h,
574 struct GNUNET_TIME_Relative timeout,
575 const char* sensorname, size_t sensorname_len,
576 GNUNET_SENSOR_SensorIteratorCB callback, void *callback_cls)
577{
578 struct GNUNET_SENSOR_SensorIteratorContext *ic;
579 struct GNUNET_SENSOR_RequestContext *rc;
580 struct GNUNET_MessageHeader *mh;
581
582 ic = GNUNET_new (struct GNUNET_SENSOR_SensorIteratorContext);
583 if (NULL == sensorname)
584 {
585 LOG (GNUNET_ERROR_TYPE_INFO,
586 "Requesting list of sensors from SENSOR service\n");
587 rc =
588 GNUNET_malloc (sizeof (struct GNUNET_SENSOR_RequestContext) +
589 sizeof (struct GNUNET_MessageHeader));
590 rc->size = sizeof (struct GNUNET_MessageHeader);
591 mh = (struct GNUNET_MessageHeader *) &rc[1];
592 mh->size = htons(sizeof (struct GNUNET_MessageHeader));
593 mh->type = htons(GNUNET_MESSAGE_TYPE_SENSOR_GETALL);
594 }
595 else
596 {
597 LOG (GNUNET_ERROR_TYPE_INFO,
598 "Requesting information on sensor `%s' from SENSOR service\n",
599 sensorname);
600 rc =
601 GNUNET_malloc (sizeof (struct GNUNET_SENSOR_RequestContext) +
602 sizeof (struct GNUNET_MessageHeader) +
603 sensorname_len);
604 rc->size = sizeof (struct GNUNET_MessageHeader) + sensorname_len;
605 mh = (struct GNUNET_MessageHeader *) &rc[1];
606 mh->size = htons(rc->size);
607 mh->type = htons(GNUNET_MESSAGE_TYPE_SENSOR_GET);
608 memcpy(&mh[1], sensorname, sensorname_len);
609 }
610 ic->h = h;
611 ic->rc = rc;
612 ic->callback = callback;
613 ic->callback_cls = callback_cls;
614 ic->timeout = GNUNET_TIME_relative_to_absolute (timeout);
615 ic->timeout_task =
616 GNUNET_SCHEDULER_add_delayed (timeout, &signal_sensor_iteration_timeout, ic);
617 rc->cont = &sensor_iterator_start_receive;
618 rc->cont_cls = ic;
619 GNUNET_CONTAINER_DLL_insert_tail (h->rc_head, h->rc_tail, rc);
620 GNUNET_CONTAINER_DLL_insert_tail (h->ic_head,
621 h->ic_tail,
622 ic);
623 trigger_transmit (h);
624 return ic;
625}
626
627/* end of sensor_api.c */
diff --git a/src/sensor/test_sensor_api.c b/src/sensor/test_sensor_api.c
new file mode 100644
index 000000000..0967f2b3f
--- /dev/null
+++ b/src/sensor/test_sensor_api.c
@@ -0,0 +1,84 @@
1/*
2 This file is part of GNUnet.
3 (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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file sensor/test_sensor_api.c
22 * @brief testcase for sensor_api.c
23 */
24#include <gnunet/platform.h>
25#include <gnunet/gnunet_util_lib.h>
26#include "gnunet_sensor_service.h"
27
28
29static int ok = 1;
30
31
32static void
33run (void *cls,
34 char *const *args,
35 const char *cfgfile,
36 const struct GNUNET_CONFIGURATION_Handle *cfg)
37{
38 ok = 0;
39}
40
41
42static int
43check ()
44{
45 char *const argv[] = { "test-sensor-api", NULL };
46 struct GNUNET_GETOPT_CommandLineOption options[] = {
47 GNUNET_GETOPT_OPTION_END
48 };
49 struct GNUNET_OS_Process *proc;
50 char *path = GNUNET_OS_get_libexec_binary_path ( "gnunet-service-sensor");
51 if (NULL == path)
52 {
53 fprintf (stderr, "Service executable not found `%s'\n", "gnunet-service-sensor");
54 return -1;
55 }
56
57 proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
58 NULL, NULL, path, "gnunet-service-sensor", NULL);
59
60 GNUNET_free (path);
61 GNUNET_assert (NULL != proc);
62 GNUNET_PROGRAM_run (1, argv, "test-sensor-api", "nohelp",
63 options, &run, &ok);
64 if (0 != GNUNET_OS_process_kill (proc, SIGTERM))
65 {
66 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
67 ok = 1;
68 }
69 GNUNET_OS_process_wait (proc);
70 GNUNET_OS_process_destroy (proc);
71 return ok;
72}
73
74
75int
76main (int argc, char *argv[])
77{
78 GNUNET_log_setup ("test_statistics_api",
79 "WARNING",
80 NULL);
81 return check ();
82}
83
84/* end of test_sensor_api.c */