diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gns/gnunet-bcd.c | 884 | ||||
-rw-r--r-- | src/namestore/gnunet-namestore-fcfsd.c | 11 |
2 files changed, 523 insertions, 372 deletions
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) |