diff options
author | Alessio Vanni <vannilla@firemail.cc> | 2021-11-25 20:47:49 +0100 |
---|---|---|
committer | Alessio Vanni <vannilla@firemail.cc> | 2021-11-25 20:47:49 +0100 |
commit | a24bbd5b39c7d26d97af357531ed05579016bd69 (patch) | |
tree | aa6094e8ce1c41f2b323ceba803701d385ba3ade /src | |
parent | 63854ee52ec8d24928c2346928a3dbea22ebd1fe (diff) | |
parent | 0bd99177d2424a76bcf26b5347bfe8ee568348e8 (diff) | |
download | gnunet-a24bbd5b39c7d26d97af357531ed05579016bd69.tar.gz gnunet-a24bbd5b39c7d26d97af357531ed05579016bd69.zip |
Merge branch 'dev/vanni/bcd-new'
Diffstat (limited to 'src')
-rw-r--r-- | src/gns/Makefile.am | 2 | ||||
-rw-r--r-- | src/gns/gnunet-bcd.c | 884 | ||||
-rw-r--r-- | src/namestore/gnunet-namestore-fcfsd.c | 11 | ||||
-rw-r--r-- | src/namestore/gnunet-namestore.c | 6 | ||||
-rw-r--r-- | src/statistics/statistics_api.c | 6 | ||||
-rw-r--r-- | src/transport/tcp_service_legacy.c | 14 | ||||
-rw-r--r-- | src/util/Makefile.am | 3 | ||||
-rw-r--r-- | src/util/gnunet-qr.c | 597 | ||||
-rw-r--r-- | src/util/service.c | 8 |
9 files changed, 954 insertions, 577 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index 3aaa734f2..ba46781f0 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am | |||
@@ -80,7 +80,9 @@ bin_PROGRAMS = \ | |||
80 | noinst_PROGRAMS = \ | 80 | noinst_PROGRAMS = \ |
81 | gnunet-gns-benchmark | 81 | gnunet-gns-benchmark |
82 | 82 | ||
83 | if HAVE_PDFLATEX | ||
83 | bin_PROGRAMS += gnunet-bcd | 84 | bin_PROGRAMS += gnunet-bcd |
85 | endif | ||
84 | 86 | ||
85 | REST_PLUGIN = libgnunet_plugin_rest_gns.la | 87 | REST_PLUGIN = libgnunet_plugin_rest_gns.la |
86 | 88 | ||
diff --git a/src/gns/gnunet-bcd.c b/src/gns/gnunet-bcd.c index a2e94089c..83efcfba5 100644 --- a/src/gns/gnunet-bcd.c +++ b/src/gns/gnunet-bcd.c | |||
@@ -30,394 +30,522 @@ | |||
30 | #include "gnunet_identity_service.h" | 30 | #include "gnunet_identity_service.h" |
31 | #include "gnunet_mhd_compat.h" | 31 | #include "gnunet_mhd_compat.h" |
32 | 32 | ||
33 | struct StaticResource | ||
34 | { | ||
35 | /** | ||
36 | * Handle to file on disk. | ||
37 | */ | ||
38 | struct GNUNET_DISK_FileHandle *handle; | ||
39 | |||
40 | /** | ||
41 | * Size in bytes of the file. | ||
42 | */ | ||
43 | uint64_t size; | ||
44 | |||
45 | /** | ||
46 | * Cached response object to send to clients. | ||
47 | */ | ||
48 | struct MHD_Response *response; | ||
49 | }; | ||
50 | |||
51 | struct ParameterMap | ||
52 | { | ||
53 | /** | ||
54 | * Name of the parameter from the request. | ||
55 | */ | ||
56 | char *name; | ||
57 | |||
58 | /** | ||
59 | * Name of the definition in the TeX output. | ||
60 | */ | ||
61 | char *definition; | ||
62 | }; | ||
63 | |||
33 | /** | 64 | /** |
34 | * Error page to display if submitted GNS key is invalid. | 65 | * Handle to the HTTP server as provided by libmicrohttpd |
35 | */ | 66 | */ |
36 | #define INVALID_GNSKEY \ | 67 | static struct MHD_Daemon *httpd = NULL; |
37 | "<html><head><title>Error</title><body>Invalid GNS public key given.</body></html>" | ||
38 | 68 | ||
39 | /** | 69 | /** |
40 | * Error page to display on 404. | 70 | * Our primary task for the HTTPD. |
41 | */ | 71 | */ |
42 | #define NOT_FOUND \ | 72 | static struct GNUNET_SCHEDULER_Task *httpd_task = NULL; |
43 | "<html><head><title>Error</title><body>404 not found</body></html>" | ||
44 | 73 | ||
45 | /** | 74 | /** |
46 | * Handle to the HTTP server as provided by libmicrohttpd | 75 | * Index file resource (simple result). |
47 | */ | 76 | */ |
48 | static struct MHD_Daemon *daemon_handle; | 77 | static struct StaticResource *index_simple = NULL; |
49 | 78 | ||
50 | /** | 79 | /** |
51 | * Our configuration. | 80 | * Index file resource (full result). |
52 | */ | 81 | */ |
53 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 82 | static struct StaticResource *index_full = NULL; |
54 | 83 | ||
55 | /** | 84 | /** |
56 | * Our primary task for the HTTPD. | 85 | * Error: invalid gns key. |
57 | */ | 86 | */ |
58 | static struct GNUNET_SCHEDULER_Task *http_task; | 87 | static struct StaticResource *key_error = NULL; |
59 | 88 | ||
60 | /** | 89 | /** |
61 | * Our main website. | 90 | * Error: 404 |
62 | */ | 91 | */ |
63 | static struct MHD_Response *main_response; | 92 | static struct StaticResource *notfound_error = NULL; |
64 | 93 | ||
65 | /** | 94 | /** |
66 | * Error: invalid gns key. | 95 | * Errors after receiving the form data. |
67 | */ | 96 | */ |
68 | static struct MHD_Response *invalid_gnskey_response; | 97 | static struct StaticResource *internal_error = NULL; |
69 | 98 | ||
70 | /** | 99 | /** |
71 | * Error: 404 | 100 | * Other errors. |
72 | */ | 101 | */ |
73 | static struct MHD_Response *not_found_response; | 102 | static struct StaticResource *forbidden_error = NULL; |
74 | 103 | ||
75 | /** | 104 | /** |
76 | * Absolute name of the 'gns-bcd.tex' file. | 105 | * Full path to the TeX template file (simple result) |
77 | */ | 106 | */ |
78 | static char *resfile; | 107 | static char *tex_file_simple = NULL; |
79 | 108 | ||
80 | /** | 109 | /** |
81 | * Port number. | 110 | * Full path to the TeX template file (full result) |
82 | */ | 111 | */ |
83 | static uint16_t port = 8888; | 112 | static char *tex_file_full = NULL; |
84 | 113 | ||
114 | /** | ||
115 | * Full path to the TeX template file (PNG result) | ||
116 | */ | ||
117 | static char *tex_file_png = NULL; | ||
85 | 118 | ||
86 | struct Entry | 119 | /** |
87 | { | 120 | * Used as a sort of singleton to send exactly one 100 CONTINUE per request. |
88 | const char *formname; | 121 | */ |
89 | const char *texname; | 122 | static int continue_100 = 100; |
123 | |||
124 | /** | ||
125 | * Map of names with TeX definitions, used during PDF generation. | ||
126 | */ | ||
127 | static const struct ParameterMap pmap[] = { | ||
128 | {"prefix", "prefix"}, | ||
129 | {"name", "name"}, | ||
130 | {"suffix", "suffix"}, | ||
131 | {"street", "street"}, | ||
132 | {"city", "city"}, | ||
133 | {"phone", "phone"}, | ||
134 | {"fax", "fax"}, | ||
135 | {"email", "email"}, | ||
136 | {"homepage", "homepage"}, | ||
137 | {"org", "organization"}, | ||
138 | {"department", "department"}, | ||
139 | {"subdepartment", "subdepartment"}, | ||
140 | {"jobtitle", "jobtitle"}, | ||
141 | {NULL, NULL}, | ||
90 | }; | 142 | }; |
91 | 143 | ||
144 | /** | ||
145 | * Port number. | ||
146 | */ | ||
147 | static uint16_t port = 8888; | ||
92 | 148 | ||
93 | /** | 149 | /** |
94 | * Main request handler. | 150 | * Task ran at shutdown to clean up everything. |
151 | * | ||
152 | * @param cls unused | ||
95 | */ | 153 | */ |
96 | static MHD_RESULT | 154 | static void |
97 | access_handler_callback (void *cls, | 155 | do_shutdown (void *cls) |
98 | struct MHD_Connection *connection, | ||
99 | const char *url, | ||
100 | const char *method, | ||
101 | const char *version, | ||
102 | const char *upload_data, | ||
103 | size_t *upload_data_size, | ||
104 | void **con_cls) | ||
105 | { | 156 | { |
106 | static int dummy; | 157 | /* We cheat a bit here: the file descriptor is implicitly closed by MHD, so |
107 | static const struct Entry map[] = { { "prefix", "prefix" }, | 158 | calling `GNUNET_DISK_file_close' would generate a spurious warning message |
108 | { "name", "name" }, | 159 | in the log. Since that function does nothing but close the descriptor and |
109 | { "suffix", "suffix" }, | 160 | free the allocated memory, After destroying the response all that's left to |
110 | { "street", "street" }, | 161 | do is call `GNUNET_free'. */ |
111 | { "city", "city" }, | 162 | if (NULL != index_simple) |
112 | { "phone", "phone" }, | ||
113 | { "fax", "fax" }, | ||
114 | { "email", "email" }, | ||
115 | { "homepage", "homepage" }, | ||
116 | { "orga", "orga" }, | ||
117 | { "departmenti18n", "departmentde" }, | ||
118 | { "departmenten", "departmenten" }, | ||
119 | { "subdepartmenti18n", | ||
120 | "subdepartmentde" }, | ||
121 | { "subdepartmenten", "subdepartmenten" }, | ||
122 | { "jobtitlei18n", "jobtitlegerman" }, | ||
123 | { "jobtitleen", "jobtitleenglish" }, | ||
124 | { "subdepartmenten", "subdepartmenten" }, | ||
125 | { NULL, NULL } }; | ||
126 | |||
127 | (void) cls; | ||
128 | (void) version; | ||
129 | (void) upload_data; | ||
130 | (void) upload_data_size; | ||
131 | if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) | ||
132 | { | 163 | { |
133 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 164 | MHD_destroy_response (index_simple->response); |
134 | _ ("Refusing `%s' request to HTTP server\n"), | 165 | GNUNET_free (index_simple->handle); |
135 | method); | 166 | GNUNET_free (index_simple); |
136 | return MHD_NO; | ||
137 | } | 167 | } |
138 | if (NULL == *con_cls) | 168 | if (NULL != index_full) |
139 | { | 169 | { |
140 | (*con_cls) = &dummy; | 170 | MHD_destroy_response (index_full->response); |
141 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending 100 CONTINUE reply\n"); | 171 | GNUNET_free (index_full->handle); |
142 | return MHD_YES; /* send 100 continue */ | 172 | GNUNET_free (index_full); |
143 | } | 173 | } |
144 | if (0 == strcasecmp (url, "/")) | 174 | if (NULL != key_error) |
145 | return MHD_queue_response (connection, MHD_HTTP_OK, main_response); | ||
146 | if (0 == strcasecmp (url, "/submit.pdf")) | ||
147 | { | 175 | { |
148 | unsigned int i; | 176 | MHD_destroy_response (key_error->response); |
149 | char *p; | 177 | GNUNET_free (key_error->handle); |
150 | char *tmp; | 178 | GNUNET_free (key_error); |
151 | char *deffile; | 179 | } |
152 | struct GNUNET_IDENTITY_PublicKey pub; | 180 | if (NULL != notfound_error) |
153 | size_t slen; | 181 | { |
154 | FILE *f; | 182 | MHD_destroy_response (notfound_error->response); |
155 | struct stat st; | 183 | GNUNET_free (notfound_error->handle); |
156 | struct MHD_Response *response; | 184 | GNUNET_free (notfound_error); |
157 | int fd; | 185 | } |
158 | MHD_RESULT ret; | 186 | if (NULL != internal_error) |
159 | 187 | { | |
160 | const char *gpg_fp = MHD_lookup_connection_value (connection, | 188 | MHD_destroy_response (internal_error->response); |
161 | MHD_GET_ARGUMENT_KIND, | 189 | GNUNET_free (internal_error->handle); |
162 | "gpgfingerprint"); | 190 | GNUNET_free (internal_error); |
163 | const char *gns_nick = MHD_lookup_connection_value (connection, | 191 | } |
164 | MHD_GET_ARGUMENT_KIND, | 192 | if (NULL != forbidden_error) |
165 | "gnsnick"); | 193 | { |
166 | const char *gnskey = | 194 | MHD_destroy_response (forbidden_error->response); |
167 | MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnskey"); | 195 | GNUNET_free (forbidden_error->handle); |
168 | if ((NULL == gnskey) || | 196 | GNUNET_free (forbidden_error); |
169 | (GNUNET_OK != | ||
170 | GNUNET_IDENTITY_public_key_from_string (gnskey, | ||
171 | &pub))) | ||
172 | { | ||
173 | return MHD_queue_response (connection, | ||
174 | MHD_HTTP_OK, | ||
175 | invalid_gnskey_response); | ||
176 | } | ||
177 | tmp = GNUNET_DISK_mkdtemp (gnskey); | ||
178 | if (NULL == tmp) | ||
179 | { | ||
180 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mktemp", gnskey); | ||
181 | return MHD_NO; | ||
182 | } | ||
183 | GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "def.tex"); | ||
184 | f = fopen (deffile, "w"); | ||
185 | if (NULL == f) | ||
186 | { | ||
187 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile); | ||
188 | GNUNET_free (deffile); | ||
189 | GNUNET_DISK_directory_remove (tmp); | ||
190 | GNUNET_free (tmp); | ||
191 | return MHD_NO; | ||
192 | } | ||
193 | for (i = 0; NULL != map[i].formname; i++) | ||
194 | { | ||
195 | const char *val = MHD_lookup_connection_value (connection, | ||
196 | MHD_GET_ARGUMENT_KIND, | ||
197 | map[i].formname); | ||
198 | if (NULL != val) | ||
199 | fprintf (f, "\\def\\%s{%s}\n", map[i].texname, val); | ||
200 | else | ||
201 | fprintf (f, "\\def\\%s{}\n", map[i].texname); | ||
202 | } | ||
203 | if (NULL != gpg_fp) | ||
204 | { | ||
205 | char *gpg1; | ||
206 | char *gpg2; | ||
207 | |||
208 | slen = strlen (gpg_fp); | ||
209 | gpg1 = GNUNET_strndup (gpg_fp, slen / 2); | ||
210 | gpg2 = GNUNET_strdup (&gpg_fp[slen / 2]); | ||
211 | fprintf (f, "\\def\\gpglineone{%s}\n\\def\\gpglinetwo{%s}\n", gpg1, gpg2); | ||
212 | GNUNET_free (gpg2); | ||
213 | GNUNET_free (gpg1); | ||
214 | } | ||
215 | fprintf (f, | ||
216 | "\\def\\gns{%s/%s}\n", | ||
217 | gnskey, | ||
218 | (NULL == gns_nick) ? "" : gns_nick); | ||
219 | fclose (f); | ||
220 | GNUNET_asprintf ( | ||
221 | &p, | ||
222 | "cd %s; cp %s gns-bcd.tex | pdflatex --enable-write18 gns-bcd.tex > /dev/null 2> /dev/null", | ||
223 | tmp, | ||
224 | resfile); | ||
225 | GNUNET_free (deffile); | ||
226 | ret = system (p); | ||
227 | if (WIFSIGNALED (ret) || (0 != WEXITSTATUS (ret))) | ||
228 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "system", p); | ||
229 | GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "gns-bcd.pdf"); | ||
230 | fd = open (deffile, O_RDONLY); | ||
231 | if (-1 == fd) | ||
232 | { | ||
233 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile); | ||
234 | GNUNET_free (deffile); | ||
235 | GNUNET_free (p); | ||
236 | GNUNET_DISK_directory_remove (tmp); | ||
237 | GNUNET_free (tmp); | ||
238 | return MHD_NO; | ||
239 | } | ||
240 | GNUNET_break (0 == stat (deffile, &st)); | ||
241 | if (NULL == | ||
242 | (response = MHD_create_response_from_fd ((size_t) st.st_size, fd))) | ||
243 | { | ||
244 | GNUNET_break (0); | ||
245 | GNUNET_break (0 == close (fd)); | ||
246 | GNUNET_free (deffile); | ||
247 | GNUNET_free (p); | ||
248 | GNUNET_DISK_directory_remove (tmp); | ||
249 | GNUNET_free (tmp); | ||
250 | return MHD_NO; | ||
251 | } | ||
252 | (void) MHD_add_response_header (response, | ||
253 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
254 | "application/pdf"); | ||
255 | ret = MHD_queue_response (connection, MHD_HTTP_OK, response); | ||
256 | MHD_destroy_response (response); | ||
257 | GNUNET_free (deffile); | ||
258 | GNUNET_free (p); | ||
259 | GNUNET_DISK_directory_remove (tmp); | ||
260 | GNUNET_free (tmp); | ||
261 | return ret; | ||
262 | } | 197 | } |
263 | return MHD_queue_response (connection, | ||
264 | MHD_HTTP_NOT_FOUND, | ||
265 | not_found_response); | ||
266 | } | ||
267 | |||
268 | |||
269 | /** | ||
270 | * Function that queries MHD's select sets and | ||
271 | * starts the task waiting for them. | ||
272 | */ | ||
273 | static struct GNUNET_SCHEDULER_Task * | ||
274 | prepare_daemon (struct MHD_Daemon *daemon_handle); | ||
275 | 198 | ||
199 | if (NULL != httpd_task) | ||
200 | { | ||
201 | GNUNET_SCHEDULER_cancel (httpd_task); | ||
202 | } | ||
203 | if (NULL != httpd) | ||
204 | { | ||
205 | MHD_stop_daemon (httpd); | ||
206 | } | ||
207 | } | ||
276 | 208 | ||
277 | /** | 209 | /** |
278 | * Call MHD to process pending requests and then go back | 210 | * Called when the HTTP server has some pending operations. |
279 | * and schedule the next run. | 211 | * |
212 | * @param cls unused | ||
280 | */ | 213 | */ |
281 | static void | 214 | static void |
282 | run_daemon (void *cls) | 215 | do_httpd (void *cls); |
283 | { | ||
284 | struct MHD_Daemon *daemon_handle = cls; | ||
285 | |||
286 | http_task = NULL; | ||
287 | GNUNET_assert (MHD_YES == MHD_run (daemon_handle)); | ||
288 | http_task = prepare_daemon (daemon_handle); | ||
289 | } | ||
290 | |||
291 | 216 | ||
292 | /** | 217 | /** |
293 | * Function that queries MHD's select sets and | 218 | * Schedule a task to run MHD. |
294 | * starts the task waiting for them. | ||
295 | */ | 219 | */ |
296 | static struct GNUNET_SCHEDULER_Task * | 220 | static void |
297 | prepare_daemon (struct MHD_Daemon *daemon_handle) | 221 | run_httpd (void) |
298 | { | 222 | { |
299 | struct GNUNET_SCHEDULER_Task *ret; | ||
300 | fd_set rs; | 223 | fd_set rs; |
301 | fd_set ws; | 224 | fd_set ws; |
302 | fd_set es; | 225 | fd_set es; |
303 | struct GNUNET_NETWORK_FDSet *wrs; | 226 | |
304 | struct GNUNET_NETWORK_FDSet *wws; | 227 | struct GNUNET_NETWORK_FDSet *grs = GNUNET_NETWORK_fdset_create (); |
305 | int max; | 228 | struct GNUNET_NETWORK_FDSet *gws = GNUNET_NETWORK_fdset_create (); |
306 | MHD_UNSIGNED_LONG_LONG timeout; | 229 | struct GNUNET_NETWORK_FDSet *ges = GNUNET_NETWORK_fdset_create (); |
307 | int haveto; | ||
308 | struct GNUNET_TIME_Relative tv; | ||
309 | 230 | ||
310 | FD_ZERO (&rs); | 231 | FD_ZERO (&rs); |
311 | FD_ZERO (&ws); | 232 | FD_ZERO (&ws); |
312 | FD_ZERO (&es); | 233 | FD_ZERO (&es); |
313 | wrs = GNUNET_NETWORK_fdset_create (); | 234 | |
314 | wws = GNUNET_NETWORK_fdset_create (); | 235 | int max = -1; |
315 | max = -1; | 236 | GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max)); |
316 | GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max)); | 237 | |
317 | haveto = MHD_get_timeout (daemon_handle, &timeout); | 238 | unsigned MHD_LONG_LONG timeout = 0; |
318 | if (haveto == MHD_YES) | 239 | struct GNUNET_TIME_Relative gtime = GNUNET_TIME_UNIT_FOREVER_REL; |
319 | tv.rel_value_us = (uint64_t) timeout * 1000LL; | 240 | if (MHD_YES == MHD_get_timeout (httpd, &timeout)) |
320 | else | 241 | { |
321 | tv = GNUNET_TIME_UNIT_FOREVER_REL; | 242 | gtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, |
322 | GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1); | 243 | timeout); |
323 | GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); | 244 | } |
324 | ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, | 245 | |
325 | tv, | 246 | GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); |
326 | wrs, | 247 | GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); |
327 | wws, | 248 | GNUNET_NETWORK_fdset_copy_native (ges, &es, max + 1); |
328 | &run_daemon, | 249 | |
329 | daemon_handle); | 250 | httpd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, |
330 | GNUNET_NETWORK_fdset_destroy (wrs); | 251 | gtime, |
331 | GNUNET_NETWORK_fdset_destroy (wws); | 252 | grs, |
332 | return ret; | 253 | gws, |
254 | &do_httpd, | ||
255 | NULL); | ||
256 | GNUNET_NETWORK_fdset_destroy (grs); | ||
257 | GNUNET_NETWORK_fdset_destroy (gws); | ||
258 | GNUNET_NETWORK_fdset_destroy (ges); | ||
333 | } | 259 | } |
334 | 260 | ||
261 | /** | ||
262 | * Called when the HTTP server has some pending operations. | ||
263 | * | ||
264 | * @param cls unused | ||
265 | */ | ||
266 | static void | ||
267 | do_httpd (void *cls) | ||
268 | { | ||
269 | httpd_task = NULL; | ||
270 | MHD_run (httpd); | ||
271 | run_httpd (); | ||
272 | } | ||
335 | 273 | ||
336 | /** | 274 | /** |
337 | * Start server offering our hostlist. | 275 | * Send a response back to a connected client. |
338 | * | 276 | * |
339 | * @return #GNUNET_OK on success | 277 | * @param cls unused |
278 | * @param connection the connection with the client | ||
279 | * @param url the requested address | ||
280 | * @param method the HTTP method used | ||
281 | * @param version the protocol version (including the "HTTP/" part) | ||
282 | * @param upload_data data sent with a POST request | ||
283 | * @param upload_data_size length in bytes of the POST data | ||
284 | * @param ptr used to pass data between request handling phases | ||
285 | * @return MHD_NO on error | ||
340 | */ | 286 | */ |
341 | static int | 287 | static MHD_RESULT |
342 | server_start () | 288 | create_response (void *cls, |
289 | struct MHD_Connection *connection, | ||
290 | const char *url, | ||
291 | const char *method, | ||
292 | const char *version, | ||
293 | const char *upload_data, | ||
294 | size_t *upload_data_size, | ||
295 | void **ptr) | ||
343 | { | 296 | { |
344 | if (0 == port) | 297 | (void) cls; |
298 | (void) version; | ||
299 | (void) upload_data; | ||
300 | (void) upload_data_size; | ||
301 | |||
302 | bool isget = (0 == strcmp (method, MHD_HTTP_METHOD_GET)); | ||
303 | bool ishead = (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)); | ||
304 | |||
305 | if (!isget && !ishead) | ||
345 | { | 306 | { |
346 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 307 | return MHD_queue_response (connection, |
347 | _ ("Invalid port number %u. Exiting.\n"), | 308 | MHD_HTTP_NOT_IMPLEMENTED, |
348 | port); | 309 | forbidden_error->response); |
349 | return GNUNET_SYSERR; | ||
350 | } | 310 | } |
351 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 311 | |
352 | _ ("Businesscard HTTP server starts on %u\n"), | 312 | if (ishead) |
353 | port); | ||
354 | daemon_handle = MHD_start_daemon (MHD_USE_DUAL_STACK | MHD_USE_DEBUG, | ||
355 | port, | ||
356 | NULL /* accept_policy_callback */, | ||
357 | NULL, | ||
358 | &access_handler_callback, | ||
359 | NULL, | ||
360 | MHD_OPTION_CONNECTION_LIMIT, | ||
361 | (unsigned int) 512, | ||
362 | MHD_OPTION_PER_IP_CONNECTION_LIMIT, | ||
363 | (unsigned int) 2, | ||
364 | MHD_OPTION_CONNECTION_TIMEOUT, | ||
365 | (unsigned int) 60, | ||
366 | MHD_OPTION_CONNECTION_MEMORY_LIMIT, | ||
367 | (size_t) (16 * 1024), | ||
368 | MHD_OPTION_END); | ||
369 | if (NULL == daemon_handle) | ||
370 | { | 313 | { |
371 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 314 | /* Dedicated branch in case we want to provide a different result for some |
372 | _ ("Could not start businesscard HTTP server on port %u\n"), | 315 | reason (e.g. a non-web browser application using the web UI) */ |
373 | (unsigned int) port); | 316 | return MHD_queue_response (connection, |
374 | return GNUNET_SYSERR; | 317 | MHD_HTTP_OK, |
318 | index_simple->response); | ||
375 | } | 319 | } |
376 | http_task = prepare_daemon (daemon_handle); | ||
377 | return GNUNET_OK; | ||
378 | } | ||
379 | 320 | ||
321 | /* Send a 100 CONTINUE response to tell clients that the result of the | ||
322 | request might take some time */ | ||
323 | if (NULL == *ptr) | ||
324 | { | ||
325 | *ptr = &continue_100; | ||
326 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending 100 CONTINUE\n"); | ||
327 | return MHD_YES; | ||
328 | } | ||
380 | 329 | ||
381 | /** | 330 | if (0 == strcmp ("/", url)) |
382 | * Stop HTTP server. | 331 | { |
383 | */ | 332 | return MHD_queue_response (connection, |
384 | static void | 333 | MHD_HTTP_OK, |
385 | server_stop (void *cls) | 334 | index_simple->response); |
386 | { | 335 | } |
387 | (void) cls; | 336 | |
388 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "HTTP server shutdown\n"); | 337 | if (0 == strcmp ("/full", url)) |
389 | if (NULL != http_task) | 338 | { |
339 | return MHD_queue_response (connection, | ||
340 | MHD_HTTP_OK, | ||
341 | index_full->response); | ||
342 | } | ||
343 | |||
344 | bool isfull = (0 == strcmp ("/submit/full", url)); | ||
345 | bool issimple = (0 == strcmp ("/submit/simple", url)); | ||
346 | |||
347 | if (!isfull && !issimple) | ||
348 | { | ||
349 | return MHD_queue_response (connection, | ||
350 | MHD_HTTP_NOT_FOUND, | ||
351 | notfound_error->response); | ||
352 | } | ||
353 | |||
354 | const char *gpgfp = MHD_lookup_connection_value (connection, | ||
355 | MHD_GET_ARGUMENT_KIND, | ||
356 | "gpgfingerprint"); | ||
357 | const char *gnsnick = MHD_lookup_connection_value (connection, | ||
358 | MHD_GET_ARGUMENT_KIND, | ||
359 | "gnsnick"); | ||
360 | const char *gnskey = MHD_lookup_connection_value (connection, | ||
361 | MHD_GET_ARGUMENT_KIND, | ||
362 | "gnskey"); | ||
363 | const char *qrpng = MHD_lookup_connection_value (connection, | ||
364 | MHD_GET_ARGUMENT_KIND, | ||
365 | "gnspng"); | ||
366 | |||
367 | struct GNUNET_IDENTITY_PublicKey pk; | ||
368 | if (NULL == gnskey | ||
369 | || GNUNET_OK != GNUNET_IDENTITY_public_key_from_string (gnskey, &pk)) | ||
370 | { | ||
371 | return MHD_queue_response (connection, | ||
372 | MHD_HTTP_BAD_REQUEST, | ||
373 | key_error->response); | ||
374 | } | ||
375 | |||
376 | char *tmpd = GNUNET_DISK_mkdtemp (gnskey); | ||
377 | if (NULL == tmpd) | ||
378 | { | ||
379 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mktemp", gnskey); | ||
380 | return MHD_queue_response (connection, | ||
381 | MHD_HTTP_INTERNAL_SERVER_ERROR, | ||
382 | internal_error->response); | ||
383 | } | ||
384 | |||
385 | char *defpath = NULL; | ||
386 | GNUNET_asprintf (&defpath, "%s%s%s", tmpd, DIR_SEPARATOR_STR, "def.tex"); | ||
387 | |||
388 | FILE *deffile = fopen (defpath, "w"); | ||
389 | if (NULL == deffile) | ||
390 | { | 390 | { |
391 | GNUNET_SCHEDULER_cancel (http_task); | 391 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", defpath); |
392 | http_task = NULL; | 392 | GNUNET_free (defpath); |
393 | GNUNET_DISK_directory_remove (tmpd); | ||
394 | GNUNET_free (tmpd); | ||
395 | return MHD_queue_response (connection, | ||
396 | MHD_HTTP_INTERNAL_SERVER_ERROR, | ||
397 | internal_error->response); | ||
393 | } | 398 | } |
394 | if (NULL != daemon_handle) | 399 | |
400 | GNUNET_free (defpath); | ||
401 | |||
402 | for (size_t i=0; NULL!=pmap[i].name; ++i) | ||
395 | { | 403 | { |
396 | MHD_stop_daemon (daemon_handle); | 404 | const char *value = MHD_lookup_connection_value (connection, |
397 | daemon_handle = NULL; | 405 | MHD_GET_ARGUMENT_KIND, |
406 | pmap[i].name); | ||
407 | fprintf (deffile, | ||
408 | "\\def\\%s{%s}\n", | ||
409 | pmap[i].definition, | ||
410 | (NULL == value) ? "" : value); | ||
398 | } | 411 | } |
399 | if (NULL != main_response) | 412 | |
413 | if (NULL != gpgfp) | ||
400 | { | 414 | { |
401 | MHD_destroy_response (main_response); | 415 | size_t len = strlen (gpgfp); |
402 | main_response = NULL; | 416 | char *line1 = GNUNET_strndup (gpgfp, len/2); |
417 | char *line2 = GNUNET_strdup (&gpgfp[len/2]); | ||
418 | fprintf (deffile, | ||
419 | "\\def\\gpglineone{%s}\n\\def\\gpglinetwo{%s}\n", | ||
420 | line1, | ||
421 | line2); | ||
403 | } | 422 | } |
404 | if (NULL != invalid_gnskey_response) | 423 | |
424 | fprintf (deffile, | ||
425 | "\\def\\gns{%s/%s}\n", | ||
426 | gnskey, | ||
427 | (NULL == gnsnick) ? "" : gnsnick); | ||
428 | |||
429 | fclose (deffile); | ||
430 | |||
431 | char *command = NULL; | ||
432 | GNUNET_asprintf (&command, | ||
433 | "cd %s; cp %s gns-bcd.tex; " | ||
434 | "pdflatex %s gns-bcd.tex >/dev/null 2>&1", | ||
435 | tmpd, | ||
436 | (isfull) ? tex_file_full : | ||
437 | ((NULL == qrpng) ? tex_file_simple : tex_file_png), | ||
438 | (NULL == qrpng) ? "" : "-shell-escape"); | ||
439 | |||
440 | int ret = system (command); | ||
441 | |||
442 | GNUNET_free (command); | ||
443 | |||
444 | if (WIFSIGNALED (ret) || 0 != WEXITSTATUS (ret)) | ||
405 | { | 445 | { |
406 | MHD_destroy_response (invalid_gnskey_response); | 446 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "system", command); |
407 | invalid_gnskey_response = NULL; | ||
408 | } | 447 | } |
409 | if (NULL != not_found_response) | 448 | |
449 | GNUNET_asprintf (&defpath, | ||
450 | "%s%s%s", | ||
451 | tmpd, | ||
452 | DIR_SEPARATOR_STR, | ||
453 | (NULL == qrpng) ? "gns-bcd.pdf" : "gns-bcd.png"); | ||
454 | |||
455 | int pdf = open (defpath, O_RDONLY); | ||
456 | if (-1 == pdf) | ||
410 | { | 457 | { |
411 | MHD_destroy_response (not_found_response); | 458 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", defpath); |
412 | not_found_response = NULL; | 459 | GNUNET_free (defpath); |
460 | GNUNET_DISK_directory_remove (tmpd); | ||
461 | GNUNET_free (tmpd); | ||
462 | return MHD_queue_response (connection, | ||
463 | MHD_HTTP_INTERNAL_SERVER_ERROR, | ||
464 | internal_error->response); | ||
413 | } | 465 | } |
414 | if (NULL != resfile) | 466 | |
467 | struct stat statret; | ||
468 | GNUNET_break (0 == stat (defpath, &statret)); | ||
469 | |||
470 | GNUNET_free (defpath); | ||
471 | |||
472 | struct MHD_Response *pdfrs = | ||
473 | MHD_create_response_from_fd ((size_t) statret.st_size, pdf); | ||
474 | if (NULL == pdfrs) | ||
415 | { | 475 | { |
416 | GNUNET_free (resfile); | 476 | GNUNET_break (0); |
417 | resfile = NULL; | 477 | GNUNET_break (0 == close (pdf)); |
478 | GNUNET_DISK_directory_remove (tmpd); | ||
479 | GNUNET_free (tmpd); | ||
480 | return MHD_queue_response (connection, | ||
481 | MHD_HTTP_INTERNAL_SERVER_ERROR, | ||
482 | internal_error->response); | ||
418 | } | 483 | } |
484 | |||
485 | MHD_add_response_header (pdfrs, | ||
486 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
487 | (NULL == qrpng) ? "application/pdf" : "image/png"); | ||
488 | MHD_add_response_header (pdfrs, | ||
489 | MHD_HTTP_HEADER_CONTENT_DISPOSITION, | ||
490 | (NULL == qrpng) ? | ||
491 | "attachment; filename=\"gns-business-card.pdf\"" : | ||
492 | "attachment; filename=\"gns-qr-code.png\""); | ||
493 | MHD_RESULT r = MHD_queue_response (connection, MHD_HTTP_OK, pdfrs); | ||
494 | |||
495 | MHD_destroy_response (pdfrs); | ||
496 | GNUNET_DISK_directory_remove (tmpd); | ||
497 | GNUNET_free (tmpd); | ||
498 | |||
499 | return r; | ||
419 | } | 500 | } |
420 | 501 | ||
502 | /** | ||
503 | * Open a file on disk and generate a response for it. | ||
504 | * | ||
505 | * @param name name of the file to open | ||
506 | * @param basedir directory where the file is located | ||
507 | * @return NULL on error | ||
508 | */ | ||
509 | static struct StaticResource * | ||
510 | open_static_resource (const char *name, const char *basedir) | ||
511 | { | ||
512 | char *fullname = NULL; | ||
513 | GNUNET_asprintf (&fullname, "%s%s%s", basedir, DIR_SEPARATOR_STR, name); | ||
514 | |||
515 | struct GNUNET_DISK_FileHandle *f = | ||
516 | GNUNET_DISK_file_open (fullname, | ||
517 | GNUNET_DISK_OPEN_READ, | ||
518 | GNUNET_DISK_PERM_NONE); | ||
519 | |||
520 | GNUNET_free (fullname); | ||
521 | |||
522 | if (NULL == f) | ||
523 | { | ||
524 | return NULL; | ||
525 | } | ||
526 | |||
527 | off_t size = 0; | ||
528 | if (GNUNET_SYSERR == GNUNET_DISK_file_handle_size (f, &size)) | ||
529 | { | ||
530 | GNUNET_DISK_file_close (f); | ||
531 | return NULL; | ||
532 | } | ||
533 | |||
534 | struct MHD_Response *response = MHD_create_response_from_fd64 (size, f->fd); | ||
535 | |||
536 | if (NULL == response) | ||
537 | { | ||
538 | GNUNET_DISK_file_close (f); | ||
539 | return NULL; | ||
540 | } | ||
541 | |||
542 | struct StaticResource *res = GNUNET_new (struct StaticResource); | ||
543 | res->handle = f; | ||
544 | res->size = (uint64_t) size; | ||
545 | res->response = response; | ||
546 | |||
547 | return res; | ||
548 | } | ||
421 | 549 | ||
422 | /** | 550 | /** |
423 | * Main function that will be run. | 551 | * Main function that will be run. |
@@ -433,63 +561,84 @@ run (void *cls, | |||
433 | const char *cfgfile, | 561 | const char *cfgfile, |
434 | const struct GNUNET_CONFIGURATION_Handle *c) | 562 | const struct GNUNET_CONFIGURATION_Handle *c) |
435 | { | 563 | { |
436 | struct stat st; | ||
437 | char *dir; | ||
438 | char *fn; | ||
439 | int fd; | ||
440 | |||
441 | (void) cls; | 564 | (void) cls; |
442 | (void) args; | 565 | (void) args; |
443 | (void) cfgfile; | 566 | (void) cfgfile; |
444 | cfg = c; | 567 | |
445 | dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); | 568 | if (0 == port) |
446 | GNUNET_assert (NULL != dir); | ||
447 | GNUNET_asprintf (&fn, "%s%s%s", dir, DIR_SEPARATOR_STR, "gns-bcd.html"); | ||
448 | GNUNET_asprintf (&resfile, "%s%s%s", dir, DIR_SEPARATOR_STR, "gns-bcd.tex"); | ||
449 | GNUNET_free (dir); | ||
450 | fd = open (fn, O_RDONLY); | ||
451 | if (-1 == fd) | ||
452 | { | 569 | { |
453 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); | 570 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
454 | GNUNET_free (fn); | 571 | _ ("Invalid port number %u\n"), |
572 | port); | ||
573 | GNUNET_SCHEDULER_shutdown (); | ||
455 | return; | 574 | return; |
456 | } | 575 | } |
457 | if (0 != stat (fn, &st)) | 576 | |
577 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
578 | |||
579 | char *datadir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); | ||
580 | GNUNET_assert (NULL != datadir); | ||
581 | |||
582 | GNUNET_asprintf (&tex_file_full, | ||
583 | "%s%s%s", | ||
584 | datadir, | ||
585 | DIR_SEPARATOR_STR, | ||
586 | "gns-bcd.tex"); | ||
587 | GNUNET_asprintf (&tex_file_simple, | ||
588 | "%s%s%s", | ||
589 | datadir, | ||
590 | DIR_SEPARATOR_STR, | ||
591 | "gns-bcd-simple.tex"); | ||
592 | GNUNET_asprintf(&tex_file_png, | ||
593 | "%s%s%s", | ||
594 | datadir, | ||
595 | DIR_SEPARATOR_STR, | ||
596 | "gns-bcd-png.tex"); | ||
597 | |||
598 | index_simple = open_static_resource ("gns-bcd-simple.html", datadir); | ||
599 | index_full = open_static_resource ("gns-bcd.html", datadir); | ||
600 | key_error = open_static_resource ("gns-bcd-invalid-key.html", datadir); | ||
601 | notfound_error = open_static_resource ("gns-bcd-not-found.html", datadir); | ||
602 | internal_error = open_static_resource ("gns-bcd-internal-error.html", datadir); | ||
603 | forbidden_error = open_static_resource ("gns-bcd-forbidden.html", datadir); | ||
604 | |||
605 | GNUNET_free (datadir); | ||
606 | |||
607 | if ((NULL == index_simple) || (NULL == index_full) | ||
608 | || (NULL == key_error) || (NULL == notfound_error) | ||
609 | || (NULL == internal_error) || (NULL == forbidden_error)) | ||
458 | { | 610 | { |
459 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); | 611 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
460 | GNUNET_free (fn); | 612 | _ ("Unable to set up the daemon\n")); |
461 | GNUNET_break (0 == close (fd)); | 613 | GNUNET_SCHEDULER_shutdown (); |
462 | return; | 614 | return; |
463 | } | 615 | } |
464 | GNUNET_free (fn); | 616 | |
465 | if (NULL == | 617 | int flags = MHD_USE_DUAL_STACK | MHD_USE_DEBUG | MHD_ALLOW_SUSPEND_RESUME; |
466 | (main_response = MHD_create_response_from_fd ((size_t) st.st_size, fd))) | 618 | do |
467 | { | 619 | { |
468 | GNUNET_break (0); | 620 | httpd = MHD_start_daemon (flags, |
469 | GNUNET_break (0 == close (fd)); | 621 | port, |
622 | NULL, NULL, | ||
623 | &create_response, NULL, | ||
624 | MHD_OPTION_CONNECTION_LIMIT, 512, | ||
625 | MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2, | ||
626 | MHD_OPTION_CONNECTION_TIMEOUT, 60, | ||
627 | MHD_OPTION_CONNECTION_MEMORY_LIMIT, 16 * 1024, | ||
628 | MHD_OPTION_END); | ||
629 | flags = MHD_USE_DEBUG; | ||
630 | } while (NULL == httpd && flags != MHD_USE_DEBUG); | ||
631 | |||
632 | if (NULL == httpd) | ||
633 | { | ||
634 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
635 | _ ("Failed to start HTTP server\n")); | ||
636 | GNUNET_SCHEDULER_shutdown (); | ||
470 | return; | 637 | return; |
471 | } | 638 | } |
472 | (void) MHD_add_response_header (main_response, | ||
473 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
474 | "text/html"); | ||
475 | invalid_gnskey_response = | ||
476 | MHD_create_response_from_buffer (strlen (INVALID_GNSKEY), | ||
477 | INVALID_GNSKEY, | ||
478 | MHD_RESPMEM_PERSISTENT); | ||
479 | (void) MHD_add_response_header (invalid_gnskey_response, | ||
480 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
481 | "text/html"); | ||
482 | not_found_response = MHD_create_response_from_buffer (strlen (NOT_FOUND), | ||
483 | NOT_FOUND, | ||
484 | MHD_RESPMEM_PERSISTENT); | ||
485 | (void) MHD_add_response_header (not_found_response, | ||
486 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
487 | "text/html"); | ||
488 | if (GNUNET_OK != server_start ()) | ||
489 | return; | ||
490 | GNUNET_SCHEDULER_add_shutdown (&server_stop, NULL); | ||
491 | } | ||
492 | 639 | ||
640 | run_httpd (); | ||
641 | } | ||
493 | 642 | ||
494 | /** | 643 | /** |
495 | * The main function for gnunet-gns. | 644 | * The main function for gnunet-gns. |
@@ -502,32 +651,25 @@ int | |||
502 | main (int argc, char *const *argv) | 651 | main (int argc, char *const *argv) |
503 | { | 652 | { |
504 | struct GNUNET_GETOPT_CommandLineOption options[] = { | 653 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
505 | GNUNET_GETOPT_option_uint16 ('p', | 654 | GNUNET_GETOPT_option_uint16 ( |
506 | "port", | 655 | 'p', |
507 | "PORT", | 656 | "port", |
508 | gettext_noop ( | 657 | "PORT", |
509 | "Run HTTP serve on port PORT (default is 8888)"), | 658 | gettext_noop ("Run HTTP server on port PORT (default is 8888)"), |
510 | &port), | 659 | &port), |
511 | GNUNET_GETOPT_OPTION_END | 660 | GNUNET_GETOPT_OPTION_END, |
512 | }; | 661 | }; |
513 | int ret; | ||
514 | |||
515 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
516 | return 2; | ||
517 | GNUNET_log_setup ("gnunet-bcd", "WARNING", NULL); | ||
518 | ret = (GNUNET_OK == | ||
519 | GNUNET_PROGRAM_run (argc, | ||
520 | argv, | ||
521 | "gnunet-bcd", | ||
522 | _ ("GNUnet HTTP server to create business cards"), | ||
523 | options, | ||
524 | &run, | ||
525 | NULL)) | ||
526 | ? 0 | ||
527 | : 1; | ||
528 | GNUNET_free_nz ((void *) argv); | ||
529 | return ret; | ||
530 | } | ||
531 | 662 | ||
663 | return ((GNUNET_OK == | ||
664 | GNUNET_PROGRAM_run (argc, | ||
665 | argv, | ||
666 | "gnunet-bcd", | ||
667 | _ ("GNUnet HTTP server to create business cards"), | ||
668 | options, | ||
669 | &run, | ||
670 | NULL)) | ||
671 | ? 0 | ||
672 | : 1); | ||
673 | } | ||
532 | 674 | ||
533 | /* end of gnunet-bcd.c */ | 675 | /* end of gnunet-bcd.c */ |
diff --git a/src/namestore/gnunet-namestore-fcfsd.c b/src/namestore/gnunet-namestore-fcfsd.c index 95d4c5878..7ec9db156 100644 --- a/src/namestore/gnunet-namestore-fcfsd.c +++ b/src/namestore/gnunet-namestore-fcfsd.c | |||
@@ -205,6 +205,15 @@ do_shutdown (void *cls) | |||
205 | { | 205 | { |
206 | GNUNET_IDENTITY_disconnect (identity); | 206 | GNUNET_IDENTITY_disconnect (identity); |
207 | } | 207 | } |
208 | |||
209 | if (NULL != httpd_task) | ||
210 | { | ||
211 | GNUNET_SCHEDULER_cancel (httpd_task); | ||
212 | } | ||
213 | if (NULL != httpd) | ||
214 | { | ||
215 | MHD_stop_daemon (httpd); | ||
216 | } | ||
208 | } | 217 | } |
209 | 218 | ||
210 | 219 | ||
@@ -985,7 +994,7 @@ identity_cb (void *cls, | |||
985 | * | 994 | * |
986 | * @param name name of the file to open | 995 | * @param name name of the file to open |
987 | * @param basedir directory where the file is located | 996 | * @param basedir directory where the file is located |
988 | * @return #GNUNET_SYSERR on error | 997 | * @return NULL on error |
989 | */ | 998 | */ |
990 | static struct StaticPage * | 999 | static struct StaticPage * |
991 | open_static_page (const char *name, const char *basedir) | 1000 | open_static_page (const char *name, const char *basedir) |
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c index 92d2cf627..852d99608 100644 --- a/src/namestore/gnunet-namestore.c +++ b/src/namestore/gnunet-namestore.c | |||
@@ -1212,8 +1212,10 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
1212 | char sname[64]; | 1212 | char sname[64]; |
1213 | struct GNUNET_IDENTITY_PublicKey pkey; | 1213 | struct GNUNET_IDENTITY_PublicKey pkey; |
1214 | 1214 | ||
1215 | GNUNET_STRINGS_utf8_tolower (uri, uri); | 1215 | memset(sh, 0, 105); |
1216 | if ((2 != (sscanf (uri, "gnunet://gns/%52s/%63s", sh, sname))) || | 1216 | memset(sname, 0, 64); |
1217 | |||
1218 | if ((2 != (sscanf (uri, "gnunet://gns/%58s/%63s", sh, sname))) || | ||
1217 | (GNUNET_OK != | 1219 | (GNUNET_OK != |
1218 | GNUNET_IDENTITY_public_key_from_string (sh, &pkey))) | 1220 | GNUNET_IDENTITY_public_key_from_string (sh, &pkey))) |
1219 | { | 1221 | { |
diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c index d6c2680b8..6e6acb3e5 100644 --- a/src/statistics/statistics_api.c +++ b/src/statistics/statistics_api.c | |||
@@ -270,11 +270,11 @@ update_memory_statistics (struct GNUNET_STATISTICS_Handle *h) | |||
270 | 270 | ||
271 | if (GNUNET_NO != h->do_destroy) | 271 | if (GNUNET_NO != h->do_destroy) |
272 | return; | 272 | return; |
273 | #if HAVE_MALLINFO | 273 | #if HAVE_MALLINFO2 |
274 | { | 274 | { |
275 | struct mallinfo mi; | 275 | struct mallinfo2 mi; |
276 | 276 | ||
277 | mi = mallinfo (); | 277 | mi = mallinfo2 (); |
278 | current_heap_size = mi.uordblks + mi.fordblks; | 278 | current_heap_size = mi.uordblks + mi.fordblks; |
279 | } | 279 | } |
280 | #endif | 280 | #endif |
diff --git a/src/transport/tcp_service_legacy.c b/src/transport/tcp_service_legacy.c index 8606b353b..65b090187 100644 --- a/src/transport/tcp_service_legacy.c +++ b/src/transport/tcp_service_legacy.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include "gnunet_constants.h" | 29 | #include "gnunet_constants.h" |
30 | #include "gnunet_resolver_service.h" | 30 | #include "gnunet_resolver_service.h" |
31 | 31 | ||
32 | #if HAVE_MALLINFO | 32 | #if HAVE_MALLINFO2 |
33 | #include <malloc.h> | 33 | #include <malloc.h> |
34 | #include "gauger.h" | 34 | #include "gauger.h" |
35 | #endif | 35 | #endif |
@@ -1450,7 +1450,7 @@ shutdown: | |||
1450 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write"); | 1450 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write"); |
1451 | GNUNET_break (0 == close (sctx.ready_confirm_fd)); | 1451 | GNUNET_break (0 == close (sctx.ready_confirm_fd)); |
1452 | } | 1452 | } |
1453 | #if HAVE_MALLINFO | 1453 | #if HAVE_MALLINFO2 |
1454 | { | 1454 | { |
1455 | char *counter; | 1455 | char *counter; |
1456 | 1456 | ||
@@ -1462,9 +1462,9 @@ shutdown: | |||
1462 | "GAUGER_HEAP", | 1462 | "GAUGER_HEAP", |
1463 | &counter))) | 1463 | &counter))) |
1464 | { | 1464 | { |
1465 | struct mallinfo mi; | 1465 | struct mallinfo2 mi; |
1466 | 1466 | ||
1467 | mi = mallinfo (); | 1467 | mi = mallinfo2 (); |
1468 | GAUGER (service_name, counter, mi.usmblks, "blocks"); | 1468 | GAUGER (service_name, counter, mi.usmblks, "blocks"); |
1469 | GNUNET_free (counter); | 1469 | GNUNET_free (counter); |
1470 | } | 1470 | } |
@@ -1599,7 +1599,7 @@ LEGACY_SERVICE_stop (struct LEGACY_SERVICE_Context *sctx) | |||
1599 | { | 1599 | { |
1600 | unsigned int i; | 1600 | unsigned int i; |
1601 | 1601 | ||
1602 | #if HAVE_MALLINFO | 1602 | #if HAVE_MALLINFO2 |
1603 | { | 1603 | { |
1604 | char *counter; | 1604 | char *counter; |
1605 | 1605 | ||
@@ -1611,9 +1611,9 @@ LEGACY_SERVICE_stop (struct LEGACY_SERVICE_Context *sctx) | |||
1611 | "GAUGER_HEAP", | 1611 | "GAUGER_HEAP", |
1612 | &counter))) | 1612 | &counter))) |
1613 | { | 1613 | { |
1614 | struct mallinfo mi; | 1614 | struct mallinfo2 mi; |
1615 | 1615 | ||
1616 | mi = mallinfo (); | 1616 | mi = mallinfo2 (); |
1617 | GAUGER (sctx->service_name, counter, mi.usmblks, "blocks"); | 1617 | GAUGER (sctx->service_name, counter, mi.usmblks, "blocks"); |
1618 | GNUNET_free (counter); | 1618 | GNUNET_free (counter); |
1619 | } | 1619 | } |
diff --git a/src/util/Makefile.am b/src/util/Makefile.am index c3a0feccc..d21ac5e86 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am | |||
@@ -239,6 +239,9 @@ gnunet_qr_LDADD = \ | |||
239 | libgnunetutil.la \ | 239 | libgnunetutil.la \ |
240 | $(GN_LIBINTL) | 240 | $(GN_LIBINTL) |
241 | gnunet_qr_LDFLAGS= -lzbar | 241 | gnunet_qr_LDFLAGS= -lzbar |
242 | if HAVE_PNG | ||
243 | gnunet_qr_LDFLAGS += -lpng | ||
244 | endif | ||
242 | 245 | ||
243 | plugin_LTLIBRARIES = \ | 246 | plugin_LTLIBRARIES = \ |
244 | libgnunet_plugin_utiltest.la | 247 | libgnunet_plugin_utiltest.la |
diff --git a/src/util/gnunet-qr.c b/src/util/gnunet-qr.c index 451d61d40..5bccd3916 100644 --- a/src/util/gnunet-qr.c +++ b/src/util/gnunet-qr.c | |||
@@ -24,302 +24,500 @@ | |||
24 | * @author Christian Grothoff (error handling) | 24 | * @author Christian Grothoff (error handling) |
25 | */ | 25 | */ |
26 | #include <stdio.h> | 26 | #include <stdio.h> |
27 | #include <zbar.h> | ||
28 | #include <stdbool.h> | 27 | #include <stdbool.h> |
28 | #include <signal.h> | ||
29 | #include <zbar.h> | ||
30 | |||
29 | #include "platform.h" | 31 | #include "platform.h" |
30 | #include "gnunet_util_lib.h" | 32 | #include "gnunet_util_lib.h" |
31 | 33 | ||
32 | #define LOG(fmt, ...) \ | 34 | #if HAVE_PNG |
33 | if (verbose) \ | 35 | #include <png.h> |
34 | printf (fmt, ## __VA_ARGS__) | 36 | #endif |
35 | 37 | ||
36 | /** | 38 | /** |
37 | * Video device to capture from. Sane default for GNU/Linux systems. | 39 | * Global exit code. |
40 | * Set to non-zero if an error occurs after the scheduler has started. | ||
38 | */ | 41 | */ |
39 | static char *device; | 42 | static int exit_code = 0; |
40 | 43 | ||
41 | /** | 44 | /** |
42 | * --verbose option | 45 | * Video device to capture from. |
46 | * Used by default if PNG support is disabled or no PNG file is specified. | ||
47 | * Defaults to /dev/video0. | ||
43 | */ | 48 | */ |
44 | static unsigned int verbose; | 49 | static char *device = NULL; |
45 | 50 | ||
51 | #if HAVE_PNG | ||
46 | /** | 52 | /** |
47 | * --silent option | 53 | * Name of the file to read from. |
54 | * If the file is not a PNG-encoded image of a QR code, an error will be | ||
55 | * thrown. | ||
48 | */ | 56 | */ |
49 | static int silent = false; | 57 | static char *pngfilename = NULL; |
58 | #endif | ||
50 | 59 | ||
51 | /** | 60 | /** |
52 | * Handler exit code | 61 | * Requested verbosity. |
53 | */ | 62 | */ |
54 | static long unsigned int exit_code = 0; | 63 | static unsigned int verbosity = 0; |
55 | 64 | ||
56 | /** | 65 | /** |
57 | * Helper process we started. | 66 | * Child process handle. |
58 | */ | 67 | */ |
59 | static struct GNUNET_OS_Process *p; | 68 | struct GNUNET_OS_Process *childproc = NULL; |
60 | 69 | ||
61 | /** | 70 | /** |
62 | * Child signal handler. | 71 | * Child process handle for waiting. |
63 | */ | 72 | */ |
64 | static struct GNUNET_SIGNAL_Context *shc_chld; | 73 | static struct GNUNET_ChildWaitHandle *waitchildproc = NULL; |
65 | 74 | ||
66 | /** | 75 | /** |
67 | * Pipe used to communicate child death via signal. | 76 | * Macro to handle verbosity when printing messages. |
68 | */ | 77 | */ |
69 | static struct GNUNET_DISK_PipeHandle *sigpipe; | 78 | #define LOG(fmt, ...) \ |
79 | do \ | ||
80 | { \ | ||
81 | if (0 < verbosity) \ | ||
82 | { \ | ||
83 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, fmt, ##__VA_ARGS__); \ | ||
84 | if (verbosity > 1) \ | ||
85 | { \ | ||
86 | fprintf (stdout, fmt, ##__VA_ARGS__); \ | ||
87 | } \ | ||
88 | } \ | ||
89 | } \ | ||
90 | while (0) | ||
70 | 91 | ||
71 | /** | 92 | /** |
72 | * Process ID of this process at the time we installed the various | 93 | * Executed when program is terminating. |
73 | * signal handlers. | ||
74 | */ | 94 | */ |
75 | static pid_t my_pid; | 95 | static void |
96 | shutdown_program (void *cls) | ||
97 | { | ||
98 | if (NULL != waitchildproc) | ||
99 | { | ||
100 | GNUNET_wait_child_cancel (waitchildproc); | ||
101 | } | ||
102 | if (NULL != childproc) | ||
103 | { | ||
104 | /* A bit brutal, but this process is terminating so we're out of time */ | ||
105 | GNUNET_OS_process_kill (childproc, SIGKILL); | ||
106 | } | ||
107 | } | ||
76 | 108 | ||
77 | /** | 109 | /** |
78 | * Task triggered whenever we receive a SIGCHLD (child | 110 | * Callback executed when the child process terminates. |
79 | * process died) or when user presses CTRL-C. | ||
80 | * | 111 | * |
81 | * @param cls closure, NULL | 112 | * @param cls closure |
113 | * @param type status of the child process | ||
114 | * @param code the exit code of the child process | ||
82 | */ | 115 | */ |
83 | static void | 116 | static void |
84 | maint_child_death (void *cls) | 117 | wait_child (void *cls, |
118 | enum GNUNET_OS_ProcessStatusType type, | ||
119 | long unsigned int code) | ||
85 | { | 120 | { |
86 | enum GNUNET_OS_ProcessStatusType type; | 121 | GNUNET_OS_process_destroy (childproc); |
122 | childproc = NULL; | ||
123 | waitchildproc = NULL; | ||
124 | |||
125 | char *uri = cls; | ||
87 | 126 | ||
88 | if ((GNUNET_OK != GNUNET_OS_process_status (p, &type, &exit_code)) || | 127 | if (0 != exit_code) |
89 | (type != GNUNET_OS_PROCESS_EXITED)) | ||
90 | GNUNET_break (0 == GNUNET_OS_process_kill (p, GNUNET_TERM_SIG)); | ||
91 | GNUNET_SIGNAL_handler_uninstall (shc_chld); | ||
92 | shc_chld = NULL; | ||
93 | if (NULL != sigpipe) | ||
94 | { | 128 | { |
95 | GNUNET_DISK_pipe_close (sigpipe); | 129 | fprintf (stdout, _("Failed to add URI %s\n"), uri); |
96 | sigpipe = NULL; | 130 | } |
131 | else | ||
132 | { | ||
133 | fprintf (stdout, _("Added URI %s\n"), uri); | ||
97 | } | 134 | } |
98 | GNUNET_OS_process_destroy (p); | ||
99 | } | ||
100 | 135 | ||
136 | GNUNET_free (uri); | ||
101 | 137 | ||
102 | /** | 138 | GNUNET_SCHEDULER_shutdown (); |
103 | * Signal handler called for signals that causes us to wait for the child process. | ||
104 | */ | ||
105 | static void | ||
106 | sighandler_chld () | ||
107 | { | ||
108 | static char c; | ||
109 | int old_errno = errno; /* backup errno */ | ||
110 | |||
111 | if (getpid () != my_pid) | ||
112 | _exit (1); /* we have fork'ed since the signal handler was created, | ||
113 | * ignore the signal, see https://gnunet.org/vfork discussion */ | ||
114 | GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle | ||
115 | (sigpipe, GNUNET_DISK_PIPE_END_WRITE), | ||
116 | &c, sizeof(c)); | ||
117 | errno = old_errno; | ||
118 | } | 139 | } |
119 | 140 | ||
120 | |||
121 | /** | 141 | /** |
122 | * Dispatch URIs to the appropriate GNUnet helper process | 142 | * Dispatch URIs to the appropriate GNUnet helper process. |
123 | * | 143 | * |
124 | * @param cls closure | 144 | * @param cls closure |
125 | * @param uri uri to dispatch | 145 | * @param uri URI to dispatch |
126 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | 146 | * @param cfgfile name of the configuration file in use |
127 | * @param cfg configuration | 147 | * @param cfg the configuration in use |
128 | */ | 148 | */ |
129 | static void | 149 | static void |
130 | gnunet_uri (void *cls, | 150 | handle_uri (void *cls, |
131 | const char *uri, | 151 | const char *uri, |
132 | const char *cfgfile, | 152 | const char *cfgfile, |
133 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 153 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
134 | { | 154 | { |
135 | const char *orig_uri; | 155 | const char *cursor = uri; |
136 | const char *slash; | ||
137 | char *subsystem; | ||
138 | char *program; | ||
139 | struct GNUNET_SCHEDULER_Task *rt; | ||
140 | 156 | ||
141 | orig_uri = uri; | ||
142 | if (0 != strncasecmp ("gnunet://", uri, strlen ("gnunet://"))) | 157 | if (0 != strncasecmp ("gnunet://", uri, strlen ("gnunet://"))) |
143 | { | 158 | { |
144 | fprintf (stderr, | 159 | fprintf (stderr, |
145 | _ ("Invalid URI: does not start with `%s'\n"), | 160 | _("Invalid URI: does not start with `gnunet://'\n")); |
146 | "gnunet://"); | 161 | exit_code = 1; |
147 | return; | 162 | return; |
148 | } | 163 | } |
149 | uri += strlen ("gnunet://"); | 164 | |
150 | if (NULL == (slash = strchr (uri, '/'))) | 165 | cursor += strlen ("gnunet://"); |
166 | |||
167 | const char *slash = strchr (cursor, '/'); | ||
168 | if (NULL == slash) | ||
151 | { | 169 | { |
152 | fprintf (stderr, _ ("Invalid URI: fails to specify subsystem\n")); | 170 | fprintf (stderr, _("Invalid URI: fails to specify a subsystem\n")); |
171 | exit_code = 1; | ||
153 | return; | 172 | return; |
154 | } | 173 | } |
155 | subsystem = GNUNET_strndup (uri, slash - uri); | 174 | |
175 | char *subsystem = GNUNET_strndup (cursor, slash - cursor); | ||
176 | char *program = NULL; | ||
177 | |||
156 | if (GNUNET_OK != | 178 | if (GNUNET_OK != |
157 | GNUNET_CONFIGURATION_get_value_string (cfg, "uri", subsystem, &program)) | 179 | GNUNET_CONFIGURATION_get_value_string (cfg, "uri", subsystem, &program)) |
158 | { | 180 | { |
159 | fprintf (stderr, _ ("No handler known for subsystem `%s'\n"), subsystem); | 181 | fprintf (stderr, _("No known handler for subsystem `%s'\n"), subsystem); |
160 | GNUNET_free (subsystem); | 182 | GNUNET_free (subsystem); |
183 | exit_code = 1; | ||
161 | return; | 184 | return; |
162 | } | 185 | } |
186 | |||
163 | GNUNET_free (subsystem); | 187 | GNUNET_free (subsystem); |
164 | sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE); | ||
165 | GNUNET_assert (NULL != sigpipe); | ||
166 | rt = GNUNET_SCHEDULER_add_read_file ( | ||
167 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
168 | GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ), | ||
169 | &maint_child_death, | ||
170 | NULL); | ||
171 | my_pid = getpid (); | ||
172 | shc_chld = GNUNET_SIGNAL_handler_install (SIGCHLD, | ||
173 | &sighandler_chld); | ||
174 | |||
175 | { | ||
176 | char **argv = NULL; | ||
177 | unsigned int argc = 0; | ||
178 | char *u = GNUNET_strdup (program); | ||
179 | |||
180 | for (const char *tok = strtok (u, " "); | ||
181 | NULL != tok; | ||
182 | tok = strtok (NULL, " ")) | ||
183 | GNUNET_array_append (argv, | ||
184 | argc, | ||
185 | GNUNET_strdup (tok)); | ||
186 | GNUNET_array_append (argv, | ||
187 | argc, | ||
188 | GNUNET_strdup (orig_uri)); | ||
189 | GNUNET_array_append (argv, | ||
190 | argc, | ||
191 | NULL); | ||
192 | p = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ALL, | ||
193 | NULL, | ||
194 | NULL, | ||
195 | NULL, | ||
196 | argv[0], | ||
197 | argv); | ||
198 | for (unsigned int i = 0; i<argc - 1; i++) | ||
199 | GNUNET_free (argv[i]); | ||
200 | GNUNET_array_grow (argv, | ||
201 | argc, | ||
202 | 0); | ||
203 | GNUNET_free (u); | ||
204 | } | ||
205 | if (NULL == p) | ||
206 | GNUNET_SCHEDULER_cancel (rt); | ||
207 | GNUNET_free (program); | ||
208 | } | ||
209 | 188 | ||
189 | char **childargv = NULL; | ||
190 | unsigned int childargc = 0; | ||
191 | |||
192 | for (const char *token=strtok (program, " "); | ||
193 | NULL!=token; | ||
194 | token=strtok(NULL, " ")) | ||
195 | { | ||
196 | GNUNET_array_append (childargv, childargc, GNUNET_strdup (token)); | ||
197 | } | ||
198 | GNUNET_array_append (childargv, childargc, GNUNET_strdup (uri)); | ||
199 | GNUNET_array_append (childargv, childargc, NULL); | ||
200 | |||
201 | childproc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ALL, | ||
202 | NULL, | ||
203 | NULL, | ||
204 | NULL, | ||
205 | childargv[0], | ||
206 | childargv); | ||
207 | for (size_t i=0; i<childargc-1; ++i) | ||
208 | { | ||
209 | GNUNET_free (childargv[i]); | ||
210 | } | ||
211 | |||
212 | GNUNET_array_grow (childargv, childargc, 0); | ||
213 | |||
214 | if (NULL == childproc) | ||
215 | { | ||
216 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
217 | _("Unable to start child process `%s'\n"), | ||
218 | program); | ||
219 | GNUNET_free (program); | ||
220 | exit_code = 1; | ||
221 | return; | ||
222 | } | ||
223 | |||
224 | waitchildproc = GNUNET_wait_child (childproc, &wait_child, (void *)uri); | ||
225 | } | ||
210 | 226 | ||
211 | /** | 227 | /** |
212 | * Obtain QR code 'symbol' from @a proc. | 228 | * Obtain a QR code symbol from @a proc. |
213 | * | 229 | * |
214 | * @param proc zbar processor to use | 230 | * @param proc the zbar processor to use |
215 | * @return NULL on error | 231 | * @return NULL on error |
216 | */ | 232 | */ |
217 | static const zbar_symbol_t * | 233 | static const zbar_symbol_t * |
218 | get_symbol (zbar_processor_t *proc) | 234 | get_symbol (zbar_processor_t *proc) |
219 | { | 235 | { |
220 | const zbar_symbol_set_t *symbols; | ||
221 | int rc; | ||
222 | int n; | ||
223 | |||
224 | if (0 != zbar_processor_parse_config (proc, "enable")) | 236 | if (0 != zbar_processor_parse_config (proc, "enable")) |
225 | { | 237 | { |
226 | GNUNET_break (0); | 238 | GNUNET_break (0); |
227 | return NULL; | 239 | return NULL; |
228 | } | 240 | } |
229 | 241 | ||
230 | /* initialize the Processor */ | 242 | int r = zbar_processor_init (proc, device, 1); |
231 | if (NULL == device) | 243 | if (0 != r) |
232 | device = GNUNET_strdup ("/dev/video0"); | ||
233 | if (0 != (rc = zbar_processor_init (proc, device, 1))) | ||
234 | { | 244 | { |
235 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 245 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
236 | "Failed to open device `%s': %d\n", | 246 | _("Failed to open device: `%s': %d\n"), |
237 | device, | 247 | device, |
238 | rc); | 248 | r); |
239 | return NULL; | 249 | return NULL; |
240 | } | 250 | } |
241 | 251 | ||
242 | /* enable the preview window */ | 252 | r = zbar_processor_set_visible (proc, 1); |
243 | if ((0 != (rc = zbar_processor_set_visible (proc, 1))) || | 253 | r += zbar_processor_set_active (proc, 1); |
244 | (0 != (rc = zbar_processor_set_active (proc, 1)))) | 254 | if (0 != r) |
245 | { | 255 | { |
246 | GNUNET_break (0); | 256 | GNUNET_break (0); |
247 | return NULL; | 257 | return NULL; |
248 | } | 258 | } |
249 | 259 | ||
250 | /* read at least one barcode (or until window closed) */ | 260 | LOG (_("Capturing...\n")); |
251 | LOG ("Capturing\n"); | 261 | |
252 | n = zbar_process_one (proc, -1); | 262 | int n = zbar_process_one (proc, -1); |
263 | |||
264 | zbar_processor_set_active (proc, 0); | ||
265 | zbar_processor_set_visible (proc, 0); | ||
253 | 266 | ||
254 | /* hide the preview window */ | ||
255 | (void) zbar_processor_set_active (proc, 0); | ||
256 | (void) zbar_processor_set_visible (proc, 0); | ||
257 | if (-1 == n) | 267 | if (-1 == n) |
258 | return NULL; /* likely user closed the window */ | 268 | { |
259 | LOG ("Got %i images\n", n); | 269 | LOG (_("No captured images\n")); |
260 | /* extract results */ | 270 | return NULL; |
261 | symbols = zbar_processor_get_results (proc); | 271 | } |
272 | |||
273 | LOG(_("Got %d images\n"), n); | ||
274 | |||
275 | const zbar_symbol_set_t *symbols = zbar_processor_get_results (proc); | ||
262 | if (NULL == symbols) | 276 | if (NULL == symbols) |
263 | { | 277 | { |
264 | GNUNET_break (0); | 278 | GNUNET_break (0); |
265 | return NULL; | 279 | return NULL; |
266 | } | 280 | } |
281 | |||
267 | return zbar_symbol_set_first_symbol (symbols); | 282 | return zbar_symbol_set_first_symbol (symbols); |
268 | } | 283 | } |
269 | 284 | ||
270 | |||
271 | /** | 285 | /** |
272 | * Run zbar QR code parser. | 286 | * Run the zbar QR code parser. |
273 | * | 287 | * |
274 | * @return NULL on error, otherwise the URI that we found | 288 | * @return NULL on error |
275 | */ | 289 | */ |
276 | static char * | 290 | static char * |
277 | run_zbar () | 291 | run_zbar (void) |
278 | { | 292 | { |
279 | zbar_processor_t *proc; | 293 | zbar_processor_t *proc = zbar_processor_create (1); |
280 | const char *data; | ||
281 | char *ret; | ||
282 | const zbar_symbol_t *symbol; | ||
283 | |||
284 | /* configure the Processor */ | ||
285 | proc = zbar_processor_create (1); | ||
286 | if (NULL == proc) | 294 | if (NULL == proc) |
287 | { | 295 | { |
288 | GNUNET_break (0); | 296 | GNUNET_break (0); |
289 | return NULL; | 297 | return NULL; |
290 | } | 298 | } |
291 | 299 | ||
292 | symbol = get_symbol (proc); | 300 | if (NULL == device) |
301 | { | ||
302 | device = GNUNET_strdup ("/dev/video0"); | ||
303 | } | ||
304 | |||
305 | const zbar_symbol_t *symbol = get_symbol (proc); | ||
293 | if (NULL == symbol) | 306 | if (NULL == symbol) |
294 | { | 307 | { |
295 | zbar_processor_destroy (proc); | 308 | zbar_processor_destroy (proc); |
296 | return NULL; | 309 | return NULL; |
297 | } | 310 | } |
298 | data = zbar_symbol_get_data (symbol); | 311 | |
312 | const char *data = zbar_symbol_get_data (symbol); | ||
299 | if (NULL == data) | 313 | if (NULL == data) |
300 | { | 314 | { |
301 | GNUNET_break (0); | 315 | GNUNET_break (0); |
302 | zbar_processor_destroy (proc); | 316 | zbar_processor_destroy (proc); |
303 | return NULL; | 317 | return NULL; |
304 | } | 318 | } |
305 | LOG ("Found %s \"%s\"\n", | 319 | |
320 | LOG (_("Found %s: \"%s\"\n"), | ||
306 | zbar_get_symbol_name (zbar_symbol_get_type (symbol)), | 321 | zbar_get_symbol_name (zbar_symbol_get_type (symbol)), |
307 | data); | 322 | data); |
308 | ret = GNUNET_strdup (data); | 323 | |
309 | /* clean up */ | 324 | char *copy = GNUNET_strdup (data); |
325 | |||
310 | zbar_processor_destroy (proc); | 326 | zbar_processor_destroy (proc); |
311 | GNUNET_free (device); | 327 | GNUNET_free (device); |
312 | return ret; | 328 | |
329 | return copy; | ||
313 | } | 330 | } |
314 | 331 | ||
332 | #if HAVE_PNG | ||
333 | /** | ||
334 | * Decode the PNG-encoded file to a raw byte buffer. | ||
335 | * | ||
336 | * @param width[out] where to store the image width | ||
337 | * @param height[out] where to store the image height | ||
338 | */ | ||
339 | static char * | ||
340 | png_parse (uint32_t *width, uint32_t *height) | ||
341 | { | ||
342 | if (NULL == width || NULL == height) | ||
343 | { | ||
344 | return NULL; | ||
345 | } | ||
346 | |||
347 | FILE *pngfile = fopen (pngfilename, "rb"); | ||
348 | if (NULL == pngfile) | ||
349 | { | ||
350 | return NULL; | ||
351 | } | ||
352 | |||
353 | unsigned char header[8]; | ||
354 | if (8 != fread (header, 1, 8, pngfile)) | ||
355 | { | ||
356 | fclose (pngfile); | ||
357 | return NULL; | ||
358 | } | ||
359 | |||
360 | if (png_sig_cmp (header, 0, 8)) | ||
361 | { | ||
362 | fclose (pngfile); | ||
363 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
364 | _("%s is not a PNG file\n"), | ||
365 | pngfilename); | ||
366 | fprintf (stderr, _("%s is not a PNG file\n"), pngfilename); | ||
367 | return NULL; | ||
368 | } | ||
369 | |||
370 | /* libpng's default error handling might or might not conflict with GNUnet's | ||
371 | scheduler and event loop. Beware of strange interactions. */ | ||
372 | png_structp png = png_create_read_struct (PNG_LIBPNG_VER_STRING, | ||
373 | NULL, | ||
374 | NULL, | ||
375 | NULL); | ||
376 | if (NULL == png) | ||
377 | { | ||
378 | GNUNET_break (0); | ||
379 | fclose (pngfile); | ||
380 | return NULL; | ||
381 | } | ||
382 | |||
383 | png_infop pnginfo = png_create_info_struct (png); | ||
384 | if (NULL == pnginfo) | ||
385 | { | ||
386 | GNUNET_break (0); | ||
387 | png_destroy_read_struct (&png, NULL, NULL); | ||
388 | fclose (pngfile); | ||
389 | return NULL; | ||
390 | } | ||
391 | |||
392 | if (setjmp (png_jmpbuf (png))) | ||
393 | { | ||
394 | GNUNET_break (0); | ||
395 | png_destroy_read_struct (&png, &pnginfo, NULL); | ||
396 | fclose (pngfile); | ||
397 | return NULL; | ||
398 | } | ||
399 | |||
400 | png_init_io (png, pngfile); | ||
401 | png_set_sig_bytes (png, 8); | ||
402 | |||
403 | png_read_info (png, pnginfo); | ||
404 | |||
405 | png_byte pngcolor = png_get_color_type (png, pnginfo); | ||
406 | png_byte pngdepth = png_get_bit_depth (png, pnginfo); | ||
407 | |||
408 | /* Normalize picture --- based on a zbar example */ | ||
409 | if (0 != (pngcolor & PNG_COLOR_TYPE_PALETTE)) | ||
410 | { | ||
411 | png_set_palette_to_rgb (png); | ||
412 | } | ||
413 | |||
414 | if (pngcolor == PNG_COLOR_TYPE_GRAY && pngdepth < 8) | ||
415 | { | ||
416 | png_set_expand_gray_1_2_4_to_8 (png); | ||
417 | } | ||
418 | |||
419 | if (16 == pngdepth) | ||
420 | { | ||
421 | png_set_strip_16 (png); | ||
422 | } | ||
423 | |||
424 | if (0 != (pngcolor & PNG_COLOR_MASK_ALPHA)) | ||
425 | { | ||
426 | png_set_strip_alpha (png); | ||
427 | } | ||
428 | |||
429 | if (0 != (pngcolor & PNG_COLOR_MASK_COLOR)) | ||
430 | { | ||
431 | png_set_rgb_to_gray_fixed (png, 1, -1, -1); | ||
432 | } | ||
433 | |||
434 | png_uint_32 pngwidth = png_get_image_width (png, pnginfo); | ||
435 | png_uint_32 pngheight = png_get_image_height (png, pnginfo); | ||
436 | |||
437 | char *buffer = GNUNET_new_array (pngwidth * pngheight, char); | ||
438 | png_bytepp rows = GNUNET_new_array (pngheight, png_bytep); | ||
439 | |||
440 | for (png_uint_32 i=0; i<pngheight; ++i) | ||
441 | { | ||
442 | rows[i] = (unsigned char *)buffer + (pngwidth * i); | ||
443 | } | ||
444 | |||
445 | png_read_image (png, rows); | ||
446 | |||
447 | GNUNET_free (rows); | ||
448 | fclose (pngfile); | ||
449 | |||
450 | *width = pngwidth; | ||
451 | *height = pngheight; | ||
452 | |||
453 | return buffer; | ||
454 | } | ||
455 | |||
456 | /** | ||
457 | * Parse a PNG-encoded file for a QR code. | ||
458 | * | ||
459 | * @return NULL on error | ||
460 | */ | ||
461 | static char * | ||
462 | run_png_reader (void) | ||
463 | { | ||
464 | uint32_t width = 0; | ||
465 | uint32_t height = 0; | ||
466 | char *buffer = png_parse (&width, &height); | ||
467 | if (NULL == buffer) | ||
468 | { | ||
469 | return NULL; | ||
470 | } | ||
471 | |||
472 | zbar_image_scanner_t *scanner = zbar_image_scanner_create (); | ||
473 | zbar_image_scanner_set_config (scanner,0, ZBAR_CFG_ENABLE, 1); | ||
474 | |||
475 | zbar_image_t *zimage = zbar_image_create (); | ||
476 | zbar_image_set_format (zimage, zbar_fourcc ('Y', '8', '0', '0')); | ||
477 | zbar_image_set_size (zimage, width, height); | ||
478 | zbar_image_set_data (zimage, buffer, width * height, &zbar_image_free_data); | ||
479 | |||
480 | int n = zbar_scan_image (scanner, zimage); | ||
481 | |||
482 | if (-1 == n) | ||
483 | { | ||
484 | LOG (_("No captured images\n")); | ||
485 | return NULL; | ||
486 | } | ||
487 | |||
488 | LOG(_("Got %d images\n"), n); | ||
489 | |||
490 | const zbar_symbol_t *symbol = zbar_image_first_symbol (zimage); | ||
491 | |||
492 | const char *data = zbar_symbol_get_data (symbol); | ||
493 | if (NULL == data) | ||
494 | { | ||
495 | GNUNET_break (0); | ||
496 | zbar_image_destroy (zimage); | ||
497 | zbar_image_scanner_destroy (scanner); | ||
498 | return NULL; | ||
499 | } | ||
500 | |||
501 | LOG (_("Found %s: \"%s\"\n"), | ||
502 | zbar_get_symbol_name (zbar_symbol_get_type (symbol)), | ||
503 | data); | ||
504 | |||
505 | char *copy = GNUNET_strdup (data); | ||
506 | |||
507 | zbar_image_destroy (zimage); | ||
508 | zbar_image_scanner_destroy (scanner); | ||
509 | |||
510 | return copy; | ||
511 | } | ||
512 | #endif | ||
315 | 513 | ||
316 | /** | 514 | /** |
317 | * Main function that will be run by the scheduler. | 515 | * Main function executed by the scheduler. |
318 | * | 516 | * |
319 | * @param cls closure | 517 | * @param cls closure |
320 | * @param args remaining command-line arguments | 518 | * @param args remaining command line arguments |
321 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | 519 | * @param cfgfile name of the configuration file being used |
322 | * @param cfg configuration | 520 | * @param cfg the used configuration |
323 | */ | 521 | */ |
324 | static void | 522 | static void |
325 | run (void *cls, | 523 | run (void *cls, |
@@ -327,51 +525,72 @@ run (void *cls, | |||
327 | const char *cfgfile, | 525 | const char *cfgfile, |
328 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 526 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
329 | { | 527 | { |
330 | char *data; | 528 | char *data = NULL; |
331 | 529 | ||
332 | data = run_zbar (); | 530 | GNUNET_SCHEDULER_add_shutdown (&shutdown_program, NULL); |
333 | if (NULL == data) | 531 | |
334 | return; | 532 | #if HAVE_PNG |
335 | gnunet_uri (cls, data, cfgfile, cfg); | 533 | if (NULL != pngfilename) |
336 | if (exit_code != 0) | ||
337 | { | 534 | { |
338 | printf ("Failed to add URI %s\n", data); | 535 | data = run_png_reader (); |
339 | } | 536 | } |
340 | else | 537 | else |
538 | #endif | ||
539 | { | ||
540 | data = run_zbar (); | ||
541 | } | ||
542 | |||
543 | if (NULL == data) | ||
341 | { | 544 | { |
342 | printf ("Added URI %s\n", data); | 545 | LOG (_("No data found\n")); |
546 | exit_code = 1; | ||
547 | GNUNET_SCHEDULER_shutdown (); | ||
548 | return; | ||
343 | } | 549 | } |
344 | GNUNET_free (data); | ||
345 | }; | ||
346 | 550 | ||
551 | handle_uri (cls, data, cfgfile, cfg); | ||
552 | |||
553 | if (0 != exit_code) | ||
554 | { | ||
555 | fprintf (stdout, _("Failed to add URI %s\n"), data); | ||
556 | GNUNET_free (data); | ||
557 | GNUNET_SCHEDULER_shutdown (); | ||
558 | return; | ||
559 | } | ||
560 | |||
561 | LOG (_("Dispatching the URI\n")); | ||
562 | } | ||
347 | 563 | ||
348 | int | 564 | int |
349 | main (int argc, char *const *argv) | 565 | main (int argc, char *const *argv) |
350 | { | 566 | { |
351 | int ret; | ||
352 | struct GNUNET_GETOPT_CommandLineOption options[] = { | 567 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
353 | GNUNET_GETOPT_option_string ( | 568 | GNUNET_GETOPT_option_string ( |
354 | 'd', | 569 | 'd', |
355 | "device", | 570 | "device", |
356 | "DEVICE", | 571 | "DEVICE", |
357 | gettext_noop ("use video-device DEVICE (default: /dev/video0"), | 572 | gettext_noop ("use the video device DEVICE (defaults to /dev/video0)"), |
358 | &device), | 573 | &device), |
359 | GNUNET_GETOPT_option_verbose (&verbose), | 574 | #if HAVE_PNG |
360 | GNUNET_GETOPT_option_flag ('s', | 575 | GNUNET_GETOPT_option_string ( |
361 | "silent", | 576 | 'f', |
362 | gettext_noop ("do not show preview windows"), | 577 | "file", |
363 | &silent), | 578 | "FILE", |
364 | GNUNET_GETOPT_OPTION_END | 579 | gettext_noop ("read from the PNG-encoded file FILE"), |
580 | &pngfilename), | ||
581 | #endif | ||
582 | GNUNET_GETOPT_option_verbose (&verbosity), | ||
583 | GNUNET_GETOPT_OPTION_END, | ||
365 | }; | 584 | }; |
366 | 585 | ||
367 | ret = GNUNET_PROGRAM_run ( | 586 | enum GNUNET_GenericReturnValue ret = |
368 | argc, | 587 | GNUNET_PROGRAM_run (argc, |
369 | argv, | 588 | argv, |
370 | "gnunet-qr", | 589 | "gnunet-qr", |
371 | gettext_noop ( | 590 | gettext_noop ("Scan a QR code and import the URI read"), |
372 | "Scan a QR code using a video device and import the uri read"), | 591 | options, |
373 | options, | 592 | &run, |
374 | &run, | 593 | NULL); |
375 | NULL); | 594 | |
376 | return ((GNUNET_OK == ret) && (0 == exit_code)) ? 0 : 1; | 595 | return ((GNUNET_OK == ret) && (0 == exit_code)) ? 0 : 1; |
377 | } | 596 | } |
diff --git a/src/util/service.c b/src/util/service.c index 4c647430d..df4feb0ec 100644 --- a/src/util/service.c +++ b/src/util/service.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include "gnunet_resolver_service.h" | 31 | #include "gnunet_resolver_service.h" |
32 | #include "speedup.h" | 32 | #include "speedup.h" |
33 | 33 | ||
34 | #if HAVE_MALLINFO | 34 | #if HAVE_MALLINFO2 |
35 | #include <malloc.h> | 35 | #include <malloc.h> |
36 | #include "gauger.h" | 36 | #include "gauger.h" |
37 | #endif | 37 | #endif |
@@ -2140,7 +2140,7 @@ shutdown: | |||
2140 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write"); | 2140 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write"); |
2141 | GNUNET_break (0 == close (sh.ready_confirm_fd)); | 2141 | GNUNET_break (0 == close (sh.ready_confirm_fd)); |
2142 | } | 2142 | } |
2143 | #if HAVE_MALLINFO | 2143 | #if HAVE_MALLINFO2 |
2144 | { | 2144 | { |
2145 | char *counter; | 2145 | char *counter; |
2146 | 2146 | ||
@@ -2152,9 +2152,9 @@ shutdown: | |||
2152 | "GAUGER_HEAP", | 2152 | "GAUGER_HEAP", |
2153 | &counter))) | 2153 | &counter))) |
2154 | { | 2154 | { |
2155 | struct mallinfo mi; | 2155 | struct mallinfo2 mi; |
2156 | 2156 | ||
2157 | mi = mallinfo (); | 2157 | mi = mallinfo2 (); |
2158 | GAUGER (service_name, counter, mi.usmblks, "blocks"); | 2158 | GAUGER (service_name, counter, mi.usmblks, "blocks"); |
2159 | GNUNET_free (counter); | 2159 | GNUNET_free (counter); |
2160 | } | 2160 | } |