-fixing
[oweals/gnunet.git] / src / mesh / gnunet-service-regexprofiler.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010, 2011, 2012 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-service-regexprofiler.c
23  * @brief service 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  */
29 #include "platform.h"
30 #include "gnunet_mesh_service.h"
31 #include "gnunet_statistics_service.h"
32
33 /**
34  * Return value from 'main'.
35  */
36 static int global_ret;
37
38 /**
39  * Configuration we use.
40  */
41 static const struct GNUNET_CONFIGURATION_Handle *cfg;
42
43 /**
44  * Handle to the statistics service.
45  */
46 static struct GNUNET_STATISTICS_Handle *stats_handle;
47
48 /**
49  * Peer's mesh handle.
50  */
51 struct GNUNET_MESH_Handle *mesh_handle;
52
53 /**
54  * Peer's mesh tunnel handle.
55  */
56 struct GNUNET_MESH_Tunnel *mesh_tunnel_handle;
57
58 /**
59  * Maximal path compression length for regex announcing.
60  */
61 static unsigned long long max_path_compression;
62
63 /**
64  * Name of the file containing policies that this peer should announce. One
65  * policy per line.
66  */
67 static char * policy_filename;
68
69
70 /**
71  * Task run during shutdown.
72  *
73  * @param cls unused
74  * @param tc unused
75  */
76 static void
77 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
78 {
79   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
80
81   if (NULL != mesh_tunnel_handle)
82   {
83     GNUNET_MESH_tunnel_destroy (mesh_tunnel_handle);
84     mesh_tunnel_handle = NULL;
85   }
86
87   if (NULL != mesh_handle)
88   {
89     GNUNET_MESH_disconnect (mesh_handle);
90     mesh_handle = NULL;
91   }
92
93   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
94 }
95
96
97 /**
98  * Announce the given regular expression using Mesh and the path compression
99  * length read from config.
100  *
101  * @param regex regular expression to announce on this peer's mesh.
102  */
103 static void
104 announce_regex (const char * regex)
105 {
106   if (NULL == regex || 0 == strlen (regex))
107   {
108     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot announce empty regex\n");
109     return;
110   }
111
112   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Announcing regex: %s\n", regex);
113   GNUNET_STATISTICS_update (stats_handle, "# regexes announced", 1, GNUNET_NO);
114   GNUNET_MESH_announce_regex (mesh_handle, regex, (unsigned int)max_path_compression);
115 }
116
117
118 /**
119  * Main function that will be run by the scheduler.
120  *
121  * @param cls closure
122  * @param server the initialized server
123  * @param cfg_ configuration
124  */
125 static void
126 run (void *cls,
127      struct GNUNET_SERVER_Handle *server,
128      const struct GNUNET_CONFIGURATION_Handle *cfg_)
129 {
130   char *regex;
131   char *data;
132   char *buf;
133   uint64_t filesize;
134   unsigned int offset;
135   GNUNET_MESH_ApplicationType app;
136
137   static struct GNUNET_MESH_MessageHandler handlers[] = {
138     {NULL, 0, 0}
139   };
140
141   cfg = cfg_;
142
143   if (GNUNET_OK !=
144       GNUNET_CONFIGURATION_get_value_number (cfg, "REGEXPROFILER", "MAX_PATH_COMPRESSION",
145                                              &max_path_compression))
146   {
147     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
148                 _
149                 ("%s service is lacking key configuration settings (%s).  Exiting.\n"),
150                 "regexprofiler", "max_path_compression");
151     global_ret = GNUNET_SYSERR;
152     GNUNET_SCHEDULER_shutdown ();
153     return;
154   }
155
156   if (GNUNET_OK !=
157       GNUNET_CONFIGURATION_get_value_filename (cfg, "REGEXPROFILER", "POLICY_FILE",
158                                                &policy_filename))
159   {
160     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
161                 _
162                 ("%s service is lacking key configuration settings (%s).  Exiting.\n"),
163                 "regexprofiler", "policy_file");
164     global_ret = GNUNET_SYSERR;
165     GNUNET_SCHEDULER_shutdown ();
166     return;
167   }
168
169   stats_handle = GNUNET_STATISTICS_create ("regexprofiler", cfg);
170
171   app = (GNUNET_MESH_ApplicationType)0;
172
173   mesh_handle =
174     GNUNET_MESH_connect (cfg, NULL, NULL, NULL, handlers, &app);
175
176   if (NULL == mesh_handle)
177   {
178     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not acquire mesh handle. Exiting.\n");
179     global_ret = GNUNET_SYSERR;
180     GNUNET_SCHEDULER_shutdown ();
181     return;
182   }
183
184   /* Announcing regexes from policy_filename */
185   if (GNUNET_YES != GNUNET_DISK_file_test (policy_filename))
186   {
187     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
188                 "Could not find policy file %s\n", policy_filename);
189     return;
190   }
191   if (GNUNET_OK != GNUNET_DISK_file_size (policy_filename, &filesize, GNUNET_YES, GNUNET_YES))
192     filesize = 0;
193   if (0 == filesize)
194   {
195     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Policy file %s is empty.\n", policy_filename);
196     return;
197   }
198   data = GNUNET_malloc (filesize);
199   if (filesize != GNUNET_DISK_fn_read (policy_filename, data, filesize))
200   {
201     GNUNET_free (data);
202     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not read policy file %s.\n",
203                 policy_filename);
204     return;
205   }
206   buf = data;
207   offset = 0;
208   regex = NULL;
209   while (offset < (filesize - 1))
210   {
211     offset++;
212     if (((data[offset] == '\n')) && (buf != &data[offset]))
213     {
214       data[offset] = '\0';
215       regex = buf;
216       GNUNET_assert (NULL != regex);
217       announce_regex (regex);
218       buf = &data[offset + 1];
219     }
220     else if ((data[offset] == '\n') || (data[offset] == '\0'))
221           buf = &data[offset + 1];
222   }
223   GNUNET_free (data);
224
225   /* Scheduled the task to clean up when shutdown is called */
226   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
227                                 NULL);
228 }
229
230
231 /**
232  * The main function of the regexprofiler service.
233  *
234  * @param argc number of arguments from the command line
235  * @param argv command line arguments
236  * @return 0 ok, 1 on error
237  */
238 int
239 main (int argc, char *const *argv)
240 {
241   return (GNUNET_OK ==
242           GNUNET_SERVICE_run (argc, argv, "regexprofiler",
243                               GNUNET_SERVICE_OPTION_NONE,
244                               &run, NULL)) ? global_ret : 1;
245 }
246
247 /* end of gnunet-service-regexprofiler.c */