aboutsummaryrefslogtreecommitdiff
path: root/src/util/helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/helper.c')
-rw-r--r--src/util/helper.c556
1 files changed, 279 insertions, 277 deletions
diff --git a/src/util/helper.c b/src/util/helper.c
index f0892a485..9ebbdb188 100644
--- a/src/util/helper.c
+++ b/src/util/helper.c
@@ -33,7 +33,8 @@
33/** 33/**
34 * Entry in the queue of messages we need to transmit to the helper. 34 * Entry in the queue of messages we need to transmit to the helper.
35 */ 35 */
36struct GNUNET_HELPER_SendHandle { 36struct GNUNET_HELPER_SendHandle
37{
37 /** 38 /**
38 * This is an entry in a DLL. 39 * This is an entry in a DLL.
39 */ 40 */
@@ -74,7 +75,8 @@ struct GNUNET_HELPER_SendHandle {
74/** 75/**
75 * The handle to a helper process. 76 * The handle to a helper process.
76 */ 77 */
77struct GNUNET_HELPER_Handle { 78struct GNUNET_HELPER_Handle
79{
78 /** 80 /**
79 * PipeHandle to receive data from the helper 81 * PipeHandle to receive data from the helper
80 */ 82 */
@@ -172,40 +174,40 @@ struct GNUNET_HELPER_Handle {
172 * @return #GNUNET_OK on success; #GNUNET_SYSERR on error 174 * @return #GNUNET_OK on success; #GNUNET_SYSERR on error
173 */ 175 */
174int 176int
175GNUNET_HELPER_kill(struct GNUNET_HELPER_Handle *h, int soft_kill) 177GNUNET_HELPER_kill (struct GNUNET_HELPER_Handle *h, int soft_kill)
176{ 178{
177 struct GNUNET_HELPER_SendHandle *sh; 179 struct GNUNET_HELPER_SendHandle *sh;
178 int ret; 180 int ret;
179 181
180 while (NULL != (sh = h->sh_head)) 182 while (NULL != (sh = h->sh_head))
181 { 183 {
182 GNUNET_CONTAINER_DLL_remove(h->sh_head, h->sh_tail, sh); 184 GNUNET_CONTAINER_DLL_remove (h->sh_head, h->sh_tail, sh);
183 if (NULL != sh->cont) 185 if (NULL != sh->cont)
184 sh->cont(sh->cont_cls, GNUNET_NO); 186 sh->cont (sh->cont_cls, GNUNET_NO);
185 GNUNET_free(sh); 187 GNUNET_free (sh);
186 } 188 }
187 if (NULL != h->restart_task) 189 if (NULL != h->restart_task)
188 { 190 {
189 GNUNET_SCHEDULER_cancel(h->restart_task); 191 GNUNET_SCHEDULER_cancel (h->restart_task);
190 h->restart_task = NULL; 192 h->restart_task = NULL;
191 } 193 }
192 if (NULL != h->read_task) 194 if (NULL != h->read_task)
193 { 195 {
194 GNUNET_SCHEDULER_cancel(h->read_task); 196 GNUNET_SCHEDULER_cancel (h->read_task);
195 h->read_task = NULL; 197 h->read_task = NULL;
196 } 198 }
197 if (NULL == h->helper_proc) 199 if (NULL == h->helper_proc)
198 return GNUNET_SYSERR; 200 return GNUNET_SYSERR;
199 if (GNUNET_YES == soft_kill) 201 if (GNUNET_YES == soft_kill)
200 { 202 {
201 /* soft-kill only possible with pipes */ 203 /* soft-kill only possible with pipes */
202 GNUNET_assert(NULL != h->helper_in); 204 GNUNET_assert (NULL != h->helper_in);
203 ret = GNUNET_DISK_pipe_close(h->helper_in); 205 ret = GNUNET_DISK_pipe_close (h->helper_in);
204 h->helper_in = NULL; 206 h->helper_in = NULL;
205 h->fh_to_helper = NULL; 207 h->fh_to_helper = NULL;
206 return ret; 208 return ret;
207 } 209 }
208 if (0 != GNUNET_OS_process_kill(h->helper_proc, GNUNET_TERM_SIG)) 210 if (0 != GNUNET_OS_process_kill (h->helper_proc, GNUNET_TERM_SIG))
209 return GNUNET_SYSERR; 211 return GNUNET_SYSERR;
210 return GNUNET_OK; 212 return GNUNET_OK;
211} 213}
@@ -220,50 +222,50 @@ GNUNET_HELPER_kill(struct GNUNET_HELPER_Handle *h, int soft_kill)
220 * @return #GNUNET_OK on success; #GNUNET_SYSERR on error 222 * @return #GNUNET_OK on success; #GNUNET_SYSERR on error
221 */ 223 */
222int 224int
223GNUNET_HELPER_wait(struct GNUNET_HELPER_Handle *h) 225GNUNET_HELPER_wait (struct GNUNET_HELPER_Handle *h)
224{ 226{
225 struct GNUNET_HELPER_SendHandle *sh; 227 struct GNUNET_HELPER_SendHandle *sh;
226 int ret; 228 int ret;
227 229
228 ret = GNUNET_SYSERR; 230 ret = GNUNET_SYSERR;
229 if (NULL != h->helper_proc) 231 if (NULL != h->helper_proc)
230 { 232 {
231 ret = GNUNET_OS_process_wait(h->helper_proc); 233 ret = GNUNET_OS_process_wait (h->helper_proc);
232 GNUNET_OS_process_destroy(h->helper_proc); 234 GNUNET_OS_process_destroy (h->helper_proc);
233 h->helper_proc = NULL; 235 h->helper_proc = NULL;
234 } 236 }
235 if (NULL != h->read_task) 237 if (NULL != h->read_task)
236 { 238 {
237 GNUNET_SCHEDULER_cancel(h->read_task); 239 GNUNET_SCHEDULER_cancel (h->read_task);
238 h->read_task = NULL; 240 h->read_task = NULL;
239 } 241 }
240 if (NULL != h->write_task) 242 if (NULL != h->write_task)
241 { 243 {
242 GNUNET_SCHEDULER_cancel(h->write_task); 244 GNUNET_SCHEDULER_cancel (h->write_task);
243 h->write_task = NULL; 245 h->write_task = NULL;
244 } 246 }
245 if (NULL != h->helper_in) 247 if (NULL != h->helper_in)
246 { 248 {
247 GNUNET_DISK_pipe_close(h->helper_in); 249 GNUNET_DISK_pipe_close (h->helper_in);
248 h->helper_in = NULL; 250 h->helper_in = NULL;
249 h->fh_to_helper = NULL; 251 h->fh_to_helper = NULL;
250 } 252 }
251 if (NULL != h->helper_out) 253 if (NULL != h->helper_out)
252 { 254 {
253 GNUNET_DISK_pipe_close(h->helper_out); 255 GNUNET_DISK_pipe_close (h->helper_out);
254 h->helper_out = NULL; 256 h->helper_out = NULL;
255 h->fh_from_helper = NULL; 257 h->fh_from_helper = NULL;
256 } 258 }
257 while (NULL != (sh = h->sh_head)) 259 while (NULL != (sh = h->sh_head))
258 { 260 {
259 GNUNET_CONTAINER_DLL_remove(h->sh_head, h->sh_tail, sh); 261 GNUNET_CONTAINER_DLL_remove (h->sh_head, h->sh_tail, sh);
260 if (NULL != sh->cont) 262 if (NULL != sh->cont)
261 sh->cont(sh->cont_cls, GNUNET_NO); 263 sh->cont (sh->cont_cls, GNUNET_NO);
262 GNUNET_free(sh); 264 GNUNET_free (sh);
263 } 265 }
264 /* purge MST buffer */ 266 /* purge MST buffer */
265 if (NULL != h->mst) 267 if (NULL != h->mst)
266 (void)GNUNET_MST_from_buffer(h->mst, NULL, 0, GNUNET_YES, GNUNET_NO); 268 (void) GNUNET_MST_from_buffer (h->mst, NULL, 0, GNUNET_YES, GNUNET_NO);
267 return ret; 269 return ret;
268} 270}
269 271
@@ -276,18 +278,18 @@ GNUNET_HELPER_wait(struct GNUNET_HELPER_Handle *h)
276 * stdin; #GNUNET_NO to signal termination by sending SIGTERM to helper 278 * stdin; #GNUNET_NO to signal termination by sending SIGTERM to helper
277 */ 279 */
278static void 280static void
279stop_helper(struct GNUNET_HELPER_Handle *h, int soft_kill) 281stop_helper (struct GNUNET_HELPER_Handle *h, int soft_kill)
280{ 282{
281 if (NULL != h->restart_task) 283 if (NULL != h->restart_task)
282 { 284 {
283 GNUNET_SCHEDULER_cancel(h->restart_task); 285 GNUNET_SCHEDULER_cancel (h->restart_task);
284 h->restart_task = NULL; 286 h->restart_task = NULL;
285 } 287 }
286 else 288 else
287 { 289 {
288 GNUNET_break(GNUNET_OK == GNUNET_HELPER_kill(h, soft_kill)); 290 GNUNET_break (GNUNET_OK == GNUNET_HELPER_kill (h, soft_kill));
289 GNUNET_break(GNUNET_OK == GNUNET_HELPER_wait(h)); 291 GNUNET_break (GNUNET_OK == GNUNET_HELPER_wait (h));
290 } 292 }
291} 293}
292 294
293 295
@@ -297,7 +299,7 @@ stop_helper(struct GNUNET_HELPER_Handle *h, int soft_kill)
297 * @param cls handle to the helper process 299 * @param cls handle to the helper process
298 */ 300 */
299static void 301static void
300restart_task(void *cls); 302restart_task (void *cls);
301 303
302 304
303/** 305/**
@@ -306,87 +308,87 @@ restart_task(void *cls);
306 * @param cls handle to the helper process 308 * @param cls handle to the helper process
307 */ 309 */
308static void 310static void
309helper_read(void *cls) 311helper_read (void *cls)
310{ 312{
311 struct GNUNET_HELPER_Handle *h = cls; 313 struct GNUNET_HELPER_Handle *h = cls;
312 char buf[GNUNET_MAX_MESSAGE_SIZE] GNUNET_ALIGN; 314 char buf[GNUNET_MAX_MESSAGE_SIZE] GNUNET_ALIGN;
313 ssize_t t; 315 ssize_t t;
314 316
315 h->read_task = NULL; 317 h->read_task = NULL;
316 t = GNUNET_DISK_file_read(h->fh_from_helper, &buf, sizeof(buf)); 318 t = GNUNET_DISK_file_read (h->fh_from_helper, &buf, sizeof(buf));
317 if (t < 0) 319 if (t < 0)
320 {
321 /* On read-error, restart the helper */
322 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
323 _ ("Error reading from `%s': %s\n"),
324 h->binary_name,
325 strerror (errno));
326 if (NULL != h->exp_cb)
318 { 327 {
319 /* On read-error, restart the helper */ 328 h->exp_cb (h->cb_cls);
320 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, 329 GNUNET_HELPER_stop (h, GNUNET_NO);
321 _("Error reading from `%s': %s\n"),
322 h->binary_name,
323 strerror(errno));
324 if (NULL != h->exp_cb)
325 {
326 h->exp_cb(h->cb_cls);
327 GNUNET_HELPER_stop(h, GNUNET_NO);
328 return;
329 }
330 stop_helper(h, GNUNET_NO);
331 /* Restart the helper */
332 h->restart_task = GNUNET_SCHEDULER_add_delayed(
333 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
334 h->retry_back_off),
335 &restart_task,
336 h);
337 return; 330 return;
338 } 331 }
332 stop_helper (h, GNUNET_NO);
333 /* Restart the helper */
334 h->restart_task = GNUNET_SCHEDULER_add_delayed (
335 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
336 h->retry_back_off),
337 &restart_task,
338 h);
339 return;
340 }
339 if (0 == t) 341 if (0 == t)
342 {
343 /* this happens if the helper is shut down via a
344 signal, so it is not a "hard" error */
345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
346 "Got 0 bytes from helper `%s' (EOF)\n",
347 h->binary_name);
348 if (NULL != h->exp_cb)
340 { 349 {
341 /* this happens if the helper is shut down via a 350 h->exp_cb (h->cb_cls);
342 signal, so it is not a "hard" error */ 351 GNUNET_HELPER_stop (h, GNUNET_NO);
343 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
344 "Got 0 bytes from helper `%s' (EOF)\n",
345 h->binary_name);
346 if (NULL != h->exp_cb)
347 {
348 h->exp_cb(h->cb_cls);
349 GNUNET_HELPER_stop(h, GNUNET_NO);
350 return;
351 }
352 stop_helper(h, GNUNET_NO);
353 /* Restart the helper */
354 h->restart_task = GNUNET_SCHEDULER_add_delayed(
355 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
356 h->retry_back_off),
357 &restart_task,
358 h);
359 return; 352 return;
360 } 353 }
361 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 354 stop_helper (h, GNUNET_NO);
362 "Got %u bytes from helper `%s'\n", 355 /* Restart the helper */
363 (unsigned int)t, 356 h->restart_task = GNUNET_SCHEDULER_add_delayed (
364 h->binary_name); 357 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
365 h->read_task = GNUNET_SCHEDULER_add_read_file(GNUNET_TIME_UNIT_FOREVER_REL, 358 h->retry_back_off),
366 h->fh_from_helper, 359 &restart_task,
367 &helper_read, 360 h);
368 h); 361 return;
362 }
363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
364 "Got %u bytes from helper `%s'\n",
365 (unsigned int) t,
366 h->binary_name);
367 h->read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
368 h->fh_from_helper,
369 &helper_read,
370 h);
369 if (GNUNET_SYSERR == 371 if (GNUNET_SYSERR ==
370 GNUNET_MST_from_buffer(h->mst, buf, t, GNUNET_NO, GNUNET_NO)) 372 GNUNET_MST_from_buffer (h->mst, buf, t, GNUNET_NO, GNUNET_NO))
373 {
374 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
375 _ ("Failed to parse inbound message from helper `%s'\n"),
376 h->binary_name);
377 if (NULL != h->exp_cb)
371 { 378 {
372 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, 379 h->exp_cb (h->cb_cls);
373 _("Failed to parse inbound message from helper `%s'\n"), 380 GNUNET_HELPER_stop (h, GNUNET_NO);
374 h->binary_name);
375 if (NULL != h->exp_cb)
376 {
377 h->exp_cb(h->cb_cls);
378 GNUNET_HELPER_stop(h, GNUNET_NO);
379 return;
380 }
381 stop_helper(h, GNUNET_NO);
382 /* Restart the helper */
383 h->restart_task = GNUNET_SCHEDULER_add_delayed(
384 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
385 h->retry_back_off),
386 &restart_task,
387 h);
388 return; 381 return;
389 } 382 }
383 stop_helper (h, GNUNET_NO);
384 /* Restart the helper */
385 h->restart_task = GNUNET_SCHEDULER_add_delayed (
386 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
387 h->retry_back_off),
388 &restart_task,
389 h);
390 return;
391 }
390} 392}
391 393
392 394
@@ -396,55 +398,55 @@ helper_read(void *cls)
396 * @param h handle to the helper process 398 * @param h handle to the helper process
397 */ 399 */
398static void 400static void
399start_helper(struct GNUNET_HELPER_Handle *h) 401start_helper (struct GNUNET_HELPER_Handle *h)
400{ 402{
401 h->helper_in = 403 h->helper_in =
402 GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO); 404 GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO);
403 h->helper_out = 405 h->helper_out =
404 GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); 406 GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
405 if ((h->helper_in == NULL) || (h->helper_out == NULL)) 407 if ((h->helper_in == NULL) || (h->helper_out == NULL))
406 { 408 {
407 /* out of file descriptors? try again later... */ 409 /* out of file descriptors? try again later... */
408 stop_helper(h, GNUNET_NO); 410 stop_helper (h, GNUNET_NO);
409 h->restart_task = GNUNET_SCHEDULER_add_delayed( 411 h->restart_task = GNUNET_SCHEDULER_add_delayed (
410 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 412 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
411 h->retry_back_off), 413 h->retry_back_off),
412 &restart_task, 414 &restart_task,
413 h); 415 h);
414 return; 416 return;
415 } 417 }
416 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
417 "Starting HELPER process `%s'\n", 419 "Starting HELPER process `%s'\n",
418 h->binary_name); 420 h->binary_name);
419 h->fh_from_helper = 421 h->fh_from_helper =
420 GNUNET_DISK_pipe_handle(h->helper_out, GNUNET_DISK_PIPE_END_READ); 422 GNUNET_DISK_pipe_handle (h->helper_out, GNUNET_DISK_PIPE_END_READ);
421 h->fh_to_helper = 423 h->fh_to_helper =
422 GNUNET_DISK_pipe_handle(h->helper_in, GNUNET_DISK_PIPE_END_WRITE); 424 GNUNET_DISK_pipe_handle (h->helper_in, GNUNET_DISK_PIPE_END_WRITE);
423 h->helper_proc = GNUNET_OS_start_process_vap(h->with_control_pipe, 425 h->helper_proc = GNUNET_OS_start_process_vap (h->with_control_pipe,
424 GNUNET_OS_INHERIT_STD_ERR, 426 GNUNET_OS_INHERIT_STD_ERR,
425 h->helper_in, 427 h->helper_in,
426 h->helper_out, 428 h->helper_out,
427 NULL, 429 NULL,
428 h->binary_name, 430 h->binary_name,
429 h->binary_argv); 431 h->binary_argv);
430 if (NULL == h->helper_proc) 432 if (NULL == h->helper_proc)
431 { 433 {
432 /* failed to start process? try again later... */ 434 /* failed to start process? try again later... */
433 stop_helper(h, GNUNET_NO); 435 stop_helper (h, GNUNET_NO);
434 h->restart_task = GNUNET_SCHEDULER_add_delayed( 436 h->restart_task = GNUNET_SCHEDULER_add_delayed (
435 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 437 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
436 h->retry_back_off), 438 h->retry_back_off),
437 &restart_task, 439 &restart_task,
438 h); 440 h);
439 return; 441 return;
440 } 442 }
441 GNUNET_DISK_pipe_close_end(h->helper_out, GNUNET_DISK_PIPE_END_WRITE); 443 GNUNET_DISK_pipe_close_end (h->helper_out, GNUNET_DISK_PIPE_END_WRITE);
442 GNUNET_DISK_pipe_close_end(h->helper_in, GNUNET_DISK_PIPE_END_READ); 444 GNUNET_DISK_pipe_close_end (h->helper_in, GNUNET_DISK_PIPE_END_READ);
443 if (NULL != h->mst) 445 if (NULL != h->mst)
444 h->read_task = GNUNET_SCHEDULER_add_read_file(GNUNET_TIME_UNIT_FOREVER_REL, 446 h->read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
445 h->fh_from_helper, 447 h->fh_from_helper,
446 &helper_read, 448 &helper_read,
447 h); 449 h);
448} 450}
449 451
450 452
@@ -454,16 +456,16 @@ start_helper(struct GNUNET_HELPER_Handle *h)
454 * @param cls handle to the helper process 456 * @param cls handle to the helper process
455 */ 457 */
456static void 458static void
457restart_task(void *cls) 459restart_task (void *cls)
458{ 460{
459 struct GNUNET_HELPER_Handle *h = cls; 461 struct GNUNET_HELPER_Handle *h = cls;
460 462
461 h->restart_task = NULL; 463 h->restart_task = NULL;
462 h->retry_back_off++; 464 h->retry_back_off++;
463 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 465 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
464 "Restarting helper with back-off %u\n", 466 "Restarting helper with back-off %u\n",
465 h->retry_back_off); 467 h->retry_back_off);
466 start_helper(h); 468 start_helper (h);
467} 469}
468 470
469 471
@@ -484,35 +486,35 @@ restart_task(void *cls)
484 * @return the new Handle, NULL on error 486 * @return the new Handle, NULL on error
485 */ 487 */
486struct GNUNET_HELPER_Handle * 488struct GNUNET_HELPER_Handle *
487GNUNET_HELPER_start(int with_control_pipe, 489GNUNET_HELPER_start (int with_control_pipe,
488 const char *binary_name, 490 const char *binary_name,
489 char *const binary_argv[], 491 char *const binary_argv[],
490 GNUNET_MessageTokenizerCallback cb, 492 GNUNET_MessageTokenizerCallback cb,
491 GNUNET_HELPER_ExceptionCallback exp_cb, 493 GNUNET_HELPER_ExceptionCallback exp_cb,
492 void *cb_cls) 494 void *cb_cls)
493{ 495{
494 struct GNUNET_HELPER_Handle *h; 496 struct GNUNET_HELPER_Handle *h;
495 unsigned int c; 497 unsigned int c;
496 498
497 h = GNUNET_new(struct GNUNET_HELPER_Handle); 499 h = GNUNET_new (struct GNUNET_HELPER_Handle);
498 h->with_control_pipe = with_control_pipe; 500 h->with_control_pipe = with_control_pipe;
499 /* Lookup in libexec path only if we are starting gnunet helpers */ 501 /* Lookup in libexec path only if we are starting gnunet helpers */
500 if (NULL != strstr(binary_name, "gnunet")) 502 if (NULL != strstr (binary_name, "gnunet"))
501 h->binary_name = GNUNET_OS_get_libexec_binary_path(binary_name); 503 h->binary_name = GNUNET_OS_get_libexec_binary_path (binary_name);
502 else 504 else
503 h->binary_name = GNUNET_strdup(binary_name); 505 h->binary_name = GNUNET_strdup (binary_name);
504 for (c = 0; NULL != binary_argv[c]; c++) 506 for (c = 0; NULL != binary_argv[c]; c++)
505 ; 507 ;
506 h->binary_argv = GNUNET_malloc(sizeof(char *) * (c + 1)); 508 h->binary_argv = GNUNET_malloc (sizeof(char *) * (c + 1));
507 for (c = 0; NULL != binary_argv[c]; c++) 509 for (c = 0; NULL != binary_argv[c]; c++)
508 h->binary_argv[c] = GNUNET_strdup(binary_argv[c]); 510 h->binary_argv[c] = GNUNET_strdup (binary_argv[c]);
509 h->binary_argv[c] = NULL; 511 h->binary_argv[c] = NULL;
510 h->cb_cls = cb_cls; 512 h->cb_cls = cb_cls;
511 if (NULL != cb) 513 if (NULL != cb)
512 h->mst = GNUNET_MST_create(cb, h->cb_cls); 514 h->mst = GNUNET_MST_create (cb, h->cb_cls);
513 h->exp_cb = exp_cb; 515 h->exp_cb = exp_cb;
514 h->retry_back_off = 0; 516 h->retry_back_off = 0;
515 start_helper(h); 517 start_helper (h);
516 return h; 518 return h;
517} 519}
518 520
@@ -523,32 +525,32 @@ GNUNET_HELPER_start(int with_control_pipe,
523 * @param h the helper handle to free 525 * @param h the helper handle to free
524 */ 526 */
525void 527void
526GNUNET_HELPER_destroy(struct GNUNET_HELPER_Handle *h) 528GNUNET_HELPER_destroy (struct GNUNET_HELPER_Handle *h)
527{ 529{
528 unsigned int c; 530 unsigned int c;
529 struct GNUNET_HELPER_SendHandle *sh; 531 struct GNUNET_HELPER_SendHandle *sh;
530 532
531 if (NULL != h->write_task) 533 if (NULL != h->write_task)
532 { 534 {
533 GNUNET_SCHEDULER_cancel(h->write_task); 535 GNUNET_SCHEDULER_cancel (h->write_task);
534 h->write_task = NULL; 536 h->write_task = NULL;
535 } 537 }
536 GNUNET_assert(NULL == h->read_task); 538 GNUNET_assert (NULL == h->read_task);
537 GNUNET_assert(NULL == h->restart_task); 539 GNUNET_assert (NULL == h->restart_task);
538 while (NULL != (sh = h->sh_head)) 540 while (NULL != (sh = h->sh_head))
539 { 541 {
540 GNUNET_CONTAINER_DLL_remove(h->sh_head, h->sh_tail, sh); 542 GNUNET_CONTAINER_DLL_remove (h->sh_head, h->sh_tail, sh);
541 if (NULL != sh->cont) 543 if (NULL != sh->cont)
542 sh->cont(sh->cont_cls, GNUNET_SYSERR); 544 sh->cont (sh->cont_cls, GNUNET_SYSERR);
543 GNUNET_free(sh); 545 GNUNET_free (sh);
544 } 546 }
545 if (NULL != h->mst) 547 if (NULL != h->mst)
546 GNUNET_MST_destroy(h->mst); 548 GNUNET_MST_destroy (h->mst);
547 GNUNET_free(h->binary_name); 549 GNUNET_free (h->binary_name);
548 for (c = 0; h->binary_argv[c] != NULL; c++) 550 for (c = 0; h->binary_argv[c] != NULL; c++)
549 GNUNET_free(h->binary_argv[c]); 551 GNUNET_free (h->binary_argv[c]);
550 GNUNET_free(h->binary_argv); 552 GNUNET_free (h->binary_argv);
551 GNUNET_free(h); 553 GNUNET_free (h);
552} 554}
553 555
554 556
@@ -560,11 +562,11 @@ GNUNET_HELPER_destroy(struct GNUNET_HELPER_Handle *h)
560 * stdin; #GNUNET_NO to signal termination by sending SIGTERM to helper 562 * stdin; #GNUNET_NO to signal termination by sending SIGTERM to helper
561 */ 563 */
562void 564void
563GNUNET_HELPER_stop(struct GNUNET_HELPER_Handle *h, int soft_kill) 565GNUNET_HELPER_stop (struct GNUNET_HELPER_Handle *h, int soft_kill)
564{ 566{
565 h->exp_cb = NULL; 567 h->exp_cb = NULL;
566 stop_helper(h, soft_kill); 568 stop_helper (h, soft_kill);
567 GNUNET_HELPER_destroy(h); 569 GNUNET_HELPER_destroy (h);
568} 570}
569 571
570 572
@@ -574,7 +576,7 @@ GNUNET_HELPER_stop(struct GNUNET_HELPER_Handle *h, int soft_kill)
574 * @param cls handle to the helper process 576 * @param cls handle to the helper process
575 */ 577 */
576static void 578static void
577helper_write(void *cls) 579helper_write (void *cls)
578{ 580{
579 struct GNUNET_HELPER_Handle *h = cls; 581 struct GNUNET_HELPER_Handle *h = cls;
580 struct GNUNET_HELPER_SendHandle *sh; 582 struct GNUNET_HELPER_SendHandle *sh;
@@ -583,56 +585,56 @@ helper_write(void *cls)
583 585
584 h->write_task = NULL; 586 h->write_task = NULL;
585 if (NULL == (sh = h->sh_head)) 587 if (NULL == (sh = h->sh_head))
586 { 588 {
587 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Helper write had no work!\n"); 589 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Helper write had no work!\n");
588 return; /* how did this happen? */ 590 return; /* how did this happen? */
589 } 591 }
590 buf = (const char *)sh->msg; 592 buf = (const char *) sh->msg;
591 t = GNUNET_DISK_file_write(h->fh_to_helper, 593 t = GNUNET_DISK_file_write (h->fh_to_helper,
592 &buf[sh->wpos], 594 &buf[sh->wpos],
593 ntohs(sh->msg->size) - sh->wpos); 595 ntohs (sh->msg->size) - sh->wpos);
594 if (-1 == t) 596 if (-1 == t)
597 {
598 /* On write-error, restart the helper */
599 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
600 _ ("Error writing to `%s': %s\n"),
601 h->binary_name,
602 strerror (errno));
603 if (NULL != h->exp_cb)
595 { 604 {
596 /* On write-error, restart the helper */ 605 h->exp_cb (h->cb_cls);
597 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, 606 GNUNET_HELPER_stop (h, GNUNET_NO);
598 _("Error writing to `%s': %s\n"),
599 h->binary_name,
600 strerror(errno));
601 if (NULL != h->exp_cb)
602 {
603 h->exp_cb(h->cb_cls);
604 GNUNET_HELPER_stop(h, GNUNET_NO);
605 return;
606 }
607 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
608 "Stopping and restarting helper task!\n");
609 stop_helper(h, GNUNET_NO);
610 /* Restart the helper */
611 h->restart_task = GNUNET_SCHEDULER_add_delayed(
612 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
613 h->retry_back_off),
614 &restart_task,
615 h);
616 return; 607 return;
617 } 608 }
618 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
619 "Transmitted %u bytes to %s\n", 610 "Stopping and restarting helper task!\n");
620 (unsigned int)t, 611 stop_helper (h, GNUNET_NO);
621 h->binary_name); 612 /* Restart the helper */
613 h->restart_task = GNUNET_SCHEDULER_add_delayed (
614 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
615 h->retry_back_off),
616 &restart_task,
617 h);
618 return;
619 }
620 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
621 "Transmitted %u bytes to %s\n",
622 (unsigned int) t,
623 h->binary_name);
622 sh->wpos += t; 624 sh->wpos += t;
623 if (sh->wpos == ntohs(sh->msg->size)) 625 if (sh->wpos == ntohs (sh->msg->size))
624 { 626 {
625 GNUNET_CONTAINER_DLL_remove(h->sh_head, h->sh_tail, sh); 627 GNUNET_CONTAINER_DLL_remove (h->sh_head, h->sh_tail, sh);
626 if (NULL != sh->cont) 628 if (NULL != sh->cont)
627 sh->cont(sh->cont_cls, GNUNET_YES); 629 sh->cont (sh->cont_cls, GNUNET_YES);
628 GNUNET_free(sh); 630 GNUNET_free (sh);
629 } 631 }
630 if (NULL != h->sh_head) 632 if (NULL != h->sh_head)
631 h->write_task = 633 h->write_task =
632 GNUNET_SCHEDULER_add_write_file(GNUNET_TIME_UNIT_FOREVER_REL, 634 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
633 h->fh_to_helper, 635 h->fh_to_helper,
634 &helper_write, 636 &helper_write,
635 h); 637 h);
636} 638}
637 639
638 640
@@ -650,11 +652,11 @@ helper_write(void *cls)
650 * not be abortable) 652 * not be abortable)
651 */ 653 */
652struct GNUNET_HELPER_SendHandle * 654struct GNUNET_HELPER_SendHandle *
653GNUNET_HELPER_send(struct GNUNET_HELPER_Handle *h, 655GNUNET_HELPER_send (struct GNUNET_HELPER_Handle *h,
654 const struct GNUNET_MessageHeader *msg, 656 const struct GNUNET_MessageHeader *msg,
655 int can_drop, 657 int can_drop,
656 GNUNET_HELPER_Continuation cont, 658 GNUNET_HELPER_Continuation cont,
657 void *cont_cls) 659 void *cont_cls)
658{ 660{
659 struct GNUNET_HELPER_SendHandle *sh; 661 struct GNUNET_HELPER_SendHandle *sh;
660 uint16_t mlen; 662 uint16_t mlen;
@@ -663,20 +665,20 @@ GNUNET_HELPER_send(struct GNUNET_HELPER_Handle *h,
663 return NULL; 665 return NULL;
664 if ((GNUNET_YES == can_drop) && (NULL != h->sh_head)) 666 if ((GNUNET_YES == can_drop) && (NULL != h->sh_head))
665 return NULL; 667 return NULL;
666 mlen = ntohs(msg->size); 668 mlen = ntohs (msg->size);
667 sh = GNUNET_malloc(sizeof(struct GNUNET_HELPER_SendHandle) + mlen); 669 sh = GNUNET_malloc (sizeof(struct GNUNET_HELPER_SendHandle) + mlen);
668 sh->msg = (const struct GNUNET_MessageHeader *)&sh[1]; 670 sh->msg = (const struct GNUNET_MessageHeader *) &sh[1];
669 GNUNET_memcpy(&sh[1], msg, mlen); 671 GNUNET_memcpy (&sh[1], msg, mlen);
670 sh->h = h; 672 sh->h = h;
671 sh->cont = cont; 673 sh->cont = cont;
672 sh->cont_cls = cont_cls; 674 sh->cont_cls = cont_cls;
673 GNUNET_CONTAINER_DLL_insert_tail(h->sh_head, h->sh_tail, sh); 675 GNUNET_CONTAINER_DLL_insert_tail (h->sh_head, h->sh_tail, sh);
674 if (NULL == h->write_task) 676 if (NULL == h->write_task)
675 h->write_task = 677 h->write_task =
676 GNUNET_SCHEDULER_add_write_file(GNUNET_TIME_UNIT_FOREVER_REL, 678 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
677 h->fh_to_helper, 679 h->fh_to_helper,
678 &helper_write, 680 &helper_write,
679 h); 681 h);
680 682
681 return sh; 683 return sh;
682} 684}
@@ -689,22 +691,22 @@ GNUNET_HELPER_send(struct GNUNET_HELPER_Handle *h,
689 * @param sh operation to cancel 691 * @param sh operation to cancel
690 */ 692 */
691void 693void
692GNUNET_HELPER_send_cancel(struct GNUNET_HELPER_SendHandle *sh) 694GNUNET_HELPER_send_cancel (struct GNUNET_HELPER_SendHandle *sh)
693{ 695{
694 struct GNUNET_HELPER_Handle *h = sh->h; 696 struct GNUNET_HELPER_Handle *h = sh->h;
695 697
696 sh->cont = NULL; 698 sh->cont = NULL;
697 sh->cont_cls = NULL; 699 sh->cont_cls = NULL;
698 if (0 == sh->wpos) 700 if (0 == sh->wpos)
701 {
702 GNUNET_CONTAINER_DLL_remove (h->sh_head, h->sh_tail, sh);
703 GNUNET_free (sh);
704 if (NULL == h->sh_head)
699 { 705 {
700 GNUNET_CONTAINER_DLL_remove(h->sh_head, h->sh_tail, sh); 706 GNUNET_SCHEDULER_cancel (h->write_task);
701 GNUNET_free(sh); 707 h->write_task = NULL;
702 if (NULL == h->sh_head)
703 {
704 GNUNET_SCHEDULER_cancel(h->write_task);
705 h->write_task = NULL;
706 }
707 } 708 }
709 }
708} 710}
709 711
710 712