diff options
author | Bart Polot <bart@net.in.tum.de> | 2013-01-24 15:46:53 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2013-01-24 15:46:53 +0000 |
commit | 311a626e040a397213609434fc506d14880a454f (patch) | |
tree | 62a478bc42bd2ccbb8731390fd2896435635d567 /src/regex/gnunet-daemon-regexprofiler.c | |
parent | 74c58d3c492508ab3204ac06577dcdb2af2a8d11 (diff) | |
download | gnunet-311a626e040a397213609434fc506d14880a454f.tar.gz gnunet-311a626e040a397213609434fc506d14880a454f.zip |
Moved regex profiler and profiler daemon from mesh to regex, adaped to regex dht lib
Diffstat (limited to 'src/regex/gnunet-daemon-regexprofiler.c')
-rw-r--r-- | src/regex/gnunet-daemon-regexprofiler.c | 438 |
1 files changed, 438 insertions, 0 deletions
diff --git a/src/regex/gnunet-daemon-regexprofiler.c b/src/regex/gnunet-daemon-regexprofiler.c new file mode 100644 index 000000000..75d3f9c7e --- /dev/null +++ b/src/regex/gnunet-daemon-regexprofiler.c | |||
@@ -0,0 +1,438 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2012,2013 Christian Grothoff | ||
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 mesh/gnunet-daemon-regexprofiler.c | ||
23 | * @brief daemon that uses mesh to announce a regular expression. Used in | ||
24 | * conjunction with gnunet-regex-profiler to announce regexes on serveral peers | ||
25 | * without the need to explicitly connect to the mesh service running on the | ||
26 | * peer from within the profiler. | ||
27 | * @author Maximilian Szengel | ||
28 | * @author Bartlomiej Polot | ||
29 | */ | ||
30 | #include "platform.h" | ||
31 | #include "gnunet_util_lib.h" | ||
32 | #include "gnunet_regex_lib.h" | ||
33 | #include "gnunet_dht_service.h" | ||
34 | #include "gnunet_statistics_service.h" | ||
35 | |||
36 | /** | ||
37 | * Return value from 'main'. | ||
38 | */ | ||
39 | static int global_ret; | ||
40 | |||
41 | /** | ||
42 | * Configuration we use. | ||
43 | */ | ||
44 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
45 | |||
46 | /** | ||
47 | * Handle to the statistics service. | ||
48 | */ | ||
49 | static struct GNUNET_STATISTICS_Handle *stats_handle; | ||
50 | |||
51 | /** | ||
52 | * Peer's dht handle. | ||
53 | */ | ||
54 | static struct GNUNET_DHT_Handle *dht_handle; | ||
55 | |||
56 | /** | ||
57 | * Peer's regex announce handle. | ||
58 | */ | ||
59 | static struct GNUNET_REGEX_announce_handle *announce_handle; | ||
60 | |||
61 | /** | ||
62 | * Hostkey generation context | ||
63 | */ | ||
64 | static struct GNUNET_CRYPTO_RsaKeyGenerationContext *keygen; | ||
65 | |||
66 | /** | ||
67 | * Periodically reannounce regex. | ||
68 | */ | ||
69 | static GNUNET_SCHEDULER_TaskIdentifier reannounce_task; | ||
70 | |||
71 | /** | ||
72 | * How often reannounce regex. | ||
73 | */ | ||
74 | static struct GNUNET_TIME_Relative reannounce_freq; | ||
75 | |||
76 | /** | ||
77 | * Local peer's PeerID. | ||
78 | */ | ||
79 | static struct GNUNET_PeerIdentity my_full_id; | ||
80 | |||
81 | /** | ||
82 | * Maximal path compression length for regex announcing. | ||
83 | */ | ||
84 | static unsigned long long max_path_compression; | ||
85 | |||
86 | /** | ||
87 | * Name of the file containing policies that this peer should announce. One | ||
88 | * policy per line. | ||
89 | */ | ||
90 | static char * policy_filename; | ||
91 | |||
92 | /** | ||
93 | * Prefix to add before every regex we're announcing. | ||
94 | */ | ||
95 | static char * regex_prefix; | ||
96 | |||
97 | /** | ||
98 | * Regex with prefix. | ||
99 | */ | ||
100 | static char *rx_with_pfx; | ||
101 | |||
102 | |||
103 | /** | ||
104 | * Task run during shutdown. | ||
105 | * | ||
106 | * @param cls unused | ||
107 | * @param tc unused | ||
108 | */ | ||
109 | static void | ||
110 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
111 | { | ||
112 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n"); | ||
113 | |||
114 | if (NULL != keygen) | ||
115 | { | ||
116 | GNUNET_CRYPTO_rsa_key_create_stop (keygen); | ||
117 | keygen = NULL; | ||
118 | } | ||
119 | if (NULL != announce_handle) | ||
120 | { | ||
121 | GNUNET_REGEX_announce_cancel (announce_handle); | ||
122 | announce_handle = NULL; | ||
123 | } | ||
124 | |||
125 | if (NULL != dht_handle) | ||
126 | { | ||
127 | GNUNET_DHT_disconnect (dht_handle); | ||
128 | dht_handle = NULL; | ||
129 | } | ||
130 | |||
131 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); | ||
132 | } | ||
133 | |||
134 | |||
135 | /** | ||
136 | * Announce a previously announced regex re-using cached data. | ||
137 | * | ||
138 | * @param cls Clocuse (not used). | ||
139 | * @param tc TaskContext. | ||
140 | */ | ||
141 | static void | ||
142 | reannounce_regex (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
143 | { | ||
144 | reannounce_task = GNUNET_SCHEDULER_NO_TASK; | ||
145 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
146 | return; | ||
147 | reannounce_task = GNUNET_SCHEDULER_add_delayed(reannounce_freq, | ||
148 | &reannounce_regex, | ||
149 | cls); | ||
150 | } | ||
151 | |||
152 | |||
153 | /** | ||
154 | * Announce the given regular expression using Mesh and the path compression | ||
155 | * length read from config. | ||
156 | * | ||
157 | * @param regex regular expression to announce on this peer's mesh. | ||
158 | */ | ||
159 | static void | ||
160 | announce_regex (const char * regex) | ||
161 | { | ||
162 | if (NULL == regex || 0 == strlen (regex)) | ||
163 | { | ||
164 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot announce empty regex\n"); | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Announcing regex: %s\n", regex); | ||
169 | GNUNET_STATISTICS_update (stats_handle, "# regexes announced", 1, GNUNET_NO); | ||
170 | announce_handle = GNUNET_REGEX_announce (dht_handle, | ||
171 | NULL, | ||
172 | regex, | ||
173 | (unsigned int) max_path_compression, | ||
174 | stats_handle); | ||
175 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == reannounce_task); | ||
176 | reannounce_task = GNUNET_SCHEDULER_add_delayed (reannounce_freq, | ||
177 | reannounce_regex, | ||
178 | NULL); | ||
179 | } | ||
180 | |||
181 | |||
182 | /** | ||
183 | * Load regular expressions from filename into 'rxes' array. Array needs to be freed. | ||
184 | * | ||
185 | * @param filename filename of the file containing the regexes, one per line. | ||
186 | * @param rx string with the union of all regular expressions. | ||
187 | * | ||
188 | * @return number of regular expressions read from filename and in rxes array. | ||
189 | * FIXME use load regex lib function | ||
190 | */ | ||
191 | static unsigned int | ||
192 | load_regexes (const char *filename, char **rx) | ||
193 | { | ||
194 | char *data; | ||
195 | char *buf; | ||
196 | uint64_t filesize; | ||
197 | unsigned int offset; | ||
198 | unsigned int rx_cnt; | ||
199 | |||
200 | if (GNUNET_YES != GNUNET_DISK_file_test (policy_filename)) | ||
201 | { | ||
202 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
203 | "Could not find policy file %s\n", policy_filename); | ||
204 | return 0; | ||
205 | } | ||
206 | if (GNUNET_OK != GNUNET_DISK_file_size (policy_filename, &filesize, GNUNET_YES, GNUNET_YES)) | ||
207 | filesize = 0; | ||
208 | if (0 == filesize) | ||
209 | { | ||
210 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Policy file %s is empty.\n", policy_filename); | ||
211 | return 0; | ||
212 | } | ||
213 | data = GNUNET_malloc (filesize); | ||
214 | if (filesize != GNUNET_DISK_fn_read (policy_filename, data, filesize)) | ||
215 | { | ||
216 | GNUNET_free (data); | ||
217 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not read policy file %s.\n", | ||
218 | policy_filename); | ||
219 | return 0; | ||
220 | } | ||
221 | buf = data; | ||
222 | offset = 0; | ||
223 | rx_cnt = 0; | ||
224 | while (offset < (filesize - 1)) | ||
225 | { | ||
226 | offset++; | ||
227 | if ((data[offset] == '\n') && (buf != &data[offset])) | ||
228 | { | ||
229 | data[offset] = '|'; | ||
230 | buf = &data[offset + 1]; | ||
231 | rx_cnt++; | ||
232 | } | ||
233 | else if ((data[offset] == '\n') || (data[offset] == '\0')) | ||
234 | buf = &data[offset + 1]; | ||
235 | } | ||
236 | data[offset] = '\0'; | ||
237 | *rx = data; | ||
238 | |||
239 | return rx_cnt; | ||
240 | } | ||
241 | |||
242 | |||
243 | /** | ||
244 | * Callback for hostkey read/generation | ||
245 | * | ||
246 | * @param cls Closure (not used). | ||
247 | * @param pk The private key of the local peer. | ||
248 | * @param emsg Error message if applicable. | ||
249 | */ | ||
250 | static void | ||
251 | key_generation_cb (void *cls, | ||
252 | struct GNUNET_CRYPTO_RsaPrivateKey *pk, | ||
253 | const char *emsg) | ||
254 | { | ||
255 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; | ||
256 | |||
257 | keygen = NULL; | ||
258 | if (NULL == pk) | ||
259 | { | ||
260 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
261 | _("Regexprofiler could not access hostkey: %s. Exiting.\n"), | ||
262 | emsg); | ||
263 | GNUNET_SCHEDULER_shutdown (); | ||
264 | return; | ||
265 | } | ||
266 | |||
267 | GNUNET_CRYPTO_rsa_key_get_public (pk, &my_public_key); | ||
268 | GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), | ||
269 | &my_full_id.hashPubKey); | ||
270 | |||
271 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
272 | "Regexprofiler for peer [%s] starting\n", | ||
273 | GNUNET_i2s(&my_full_id)); | ||
274 | announce_regex (rx_with_pfx); | ||
275 | GNUNET_free (rx_with_pfx); | ||
276 | } | ||
277 | |||
278 | |||
279 | /** | ||
280 | * @brief Main function that will be run by the scheduler. | ||
281 | * | ||
282 | * @param cls closure | ||
283 | * @param args remaining command-line arguments | ||
284 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
285 | * @param cfg_ configuration | ||
286 | */ | ||
287 | static void | ||
288 | run (void *cls, char *const *args GNUNET_UNUSED, | ||
289 | const char *cfgfile GNUNET_UNUSED, | ||
290 | const struct GNUNET_CONFIGURATION_Handle *cfg_) | ||
291 | { | ||
292 | char *regex = NULL; | ||
293 | char *keyfile; | ||
294 | |||
295 | cfg = cfg_; | ||
296 | |||
297 | if (GNUNET_OK != | ||
298 | GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY", | ||
299 | &keyfile)) | ||
300 | { | ||
301 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
302 | _ | ||
303 | ("%s service is lacking key configuration settings (%s). Exiting.\n"), | ||
304 | "regexprofiler", "hostkey"); | ||
305 | GNUNET_SCHEDULER_shutdown (); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | if (GNUNET_OK != | ||
310 | GNUNET_CONFIGURATION_get_value_number (cfg, "REGEXPROFILER", "MAX_PATH_COMPRESSION", | ||
311 | &max_path_compression)) | ||
312 | { | ||
313 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
314 | _ | ||
315 | ("%s service is lacking key configuration settings (%s). Exiting.\n"), | ||
316 | "regexprofiler", "max_path_compression"); | ||
317 | global_ret = GNUNET_SYSERR; | ||
318 | GNUNET_SCHEDULER_shutdown (); | ||
319 | return; | ||
320 | } | ||
321 | |||
322 | if (GNUNET_OK != | ||
323 | GNUNET_CONFIGURATION_get_value_filename (cfg, "REGEXPROFILER", | ||
324 | "POLICY_FILE", &policy_filename)) | ||
325 | { | ||
326 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
327 | _ | ||
328 | ("%s service is lacking key configuration settings (%s). Exiting.\n"), | ||
329 | "regexprofiler", "policy_file"); | ||
330 | global_ret = GNUNET_SYSERR; | ||
331 | GNUNET_SCHEDULER_shutdown (); | ||
332 | return; | ||
333 | } | ||
334 | |||
335 | if (GNUNET_OK != | ||
336 | GNUNET_CONFIGURATION_get_value_string (cfg, "REGEXPROFILER", | ||
337 | "REGEX_PREFIX", ®ex_prefix)) | ||
338 | { | ||
339 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
340 | _ | ||
341 | ("%s service is lacking key configuration settings (%s). Exiting.\n"), | ||
342 | "regexprofiler", "regex_prefix"); | ||
343 | global_ret = GNUNET_SYSERR; | ||
344 | GNUNET_SCHEDULER_shutdown (); | ||
345 | return; | ||
346 | } | ||
347 | |||
348 | if (GNUNET_OK != | ||
349 | GNUNET_CONFIGURATION_get_value_time (cfg, "REGEXPROFILER", | ||
350 | "REANNOUNCE_FREQ", &reannounce_freq)) | ||
351 | { | ||
352 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
353 | "reannounce_freq not given. Using 10 minutes.\n"); | ||
354 | reannounce_freq = | ||
355 | GNUNET_TIME_relative_multiply(GNUNET_TIME_relative_get_minute_(), 10); | ||
356 | |||
357 | } | ||
358 | |||
359 | stats_handle = GNUNET_STATISTICS_create ("regexprofiler", cfg); | ||
360 | |||
361 | dht_handle = GNUNET_DHT_connect (cfg, 1); | ||
362 | |||
363 | if (NULL == dht_handle) | ||
364 | { | ||
365 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
366 | "Could not acquire dht handle. Exiting.\n"); | ||
367 | global_ret = GNUNET_SYSERR; | ||
368 | GNUNET_SCHEDULER_shutdown (); | ||
369 | return; | ||
370 | } | ||
371 | |||
372 | /* Read regexes from policy files */ | ||
373 | if (0 == load_regexes (policy_filename, ®ex)) | ||
374 | { | ||
375 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
376 | "Policy file %s contains no policies. Exiting.\n", | ||
377 | policy_filename); | ||
378 | global_ret = GNUNET_SYSERR; | ||
379 | GNUNET_SCHEDULER_shutdown (); | ||
380 | return; | ||
381 | } | ||
382 | |||
383 | /* Announcing regexes from policy_filename */ | ||
384 | GNUNET_asprintf (&rx_with_pfx, "%s(%s)", regex_prefix, regex); | ||
385 | GNUNET_free (regex); | ||
386 | |||
387 | keygen = GNUNET_CRYPTO_rsa_key_create_start (keyfile, | ||
388 | &key_generation_cb, | ||
389 | NULL); | ||
390 | GNUNET_free (keyfile); | ||
391 | |||
392 | /* Scheduled the task to clean up when shutdown is called */ | ||
393 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, | ||
394 | NULL); | ||
395 | } | ||
396 | |||
397 | |||
398 | /** | ||
399 | * The main function of the regexprofiler service. | ||
400 | * | ||
401 | * @param argc number of arguments from the command line | ||
402 | * @param argv command line arguments | ||
403 | * @return 0 ok, 1 on error | ||
404 | */ | ||
405 | int | ||
406 | main (int argc, char *const *argv) | ||
407 | { | ||
408 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
409 | GNUNET_GETOPT_OPTION_END | ||
410 | }; | ||
411 | |||
412 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
413 | return 2; | ||
414 | sleep (60); | ||
415 | return (GNUNET_OK == | ||
416 | GNUNET_PROGRAM_run (argc, argv, "regexprofiler", | ||
417 | gettext_noop | ||
418 | ("Daemon to announce regular expressions for the peer using mesh."), | ||
419 | options, &run, NULL)) ? global_ret : 1; | ||
420 | } | ||
421 | |||
422 | |||
423 | #ifdef LINUX | ||
424 | #include <malloc.h> | ||
425 | |||
426 | /** | ||
427 | * MINIMIZE heap size (way below 128k) since this process doesn't need much. | ||
428 | */ | ||
429 | void __attribute__ ((constructor)) GNUNET_ARM_memory_init () | ||
430 | { | ||
431 | mallopt (M_TRIM_THRESHOLD, 4 * 1024); | ||
432 | mallopt (M_TOP_PAD, 1 * 1024); | ||
433 | malloc_trim (0); | ||
434 | } | ||
435 | #endif | ||
436 | |||
437 | |||
438 | /* end of gnunet-daemon-regexprofiler.c */ | ||