aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/transport/plugin_transport_http_client.c320
1 files changed, 154 insertions, 166 deletions
diff --git a/src/transport/plugin_transport_http_client.c b/src/transport/plugin_transport_http_client.c
index efcfcb1c3..68b25afe5 100644
--- a/src/transport/plugin_transport_http_client.c
+++ b/src/transport/plugin_transport_http_client.c
@@ -392,7 +392,7 @@ notify_session_monitor (struct HTTP_Client_Plugin *plugin,
392 return; 392 return;
393 memset (&info, 0, sizeof (info)); 393 memset (&info, 0, sizeof (info));
394 info.state = state; 394 info.state = state;
395 info.is_inbound = GNUNET_SYSERR; /* hard to say */ 395 info.is_inbound = GNUNET_NO;
396 info.num_msg_pending = session->msgs_in_queue; 396 info.num_msg_pending = session->msgs_in_queue;
397 info.num_bytes_pending = session->bytes_in_queue; 397 info.num_bytes_pending = session->bytes_in_queue;
398 info.receive_delay = session->next_receive; 398 info.receive_delay = session->next_receive;
@@ -405,6 +405,70 @@ notify_session_monitor (struct HTTP_Client_Plugin *plugin,
405 405
406 406
407/** 407/**
408 * Delete session @a s.
409 *
410 * @param s the session to delete
411 */
412static void
413client_delete_session (struct Session *s)
414{
415 struct HTTP_Client_Plugin *plugin = s->plugin;
416 struct HTTP_Message *pos;
417 struct HTTP_Message *next;
418
419 if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task)
420 {
421 GNUNET_SCHEDULER_cancel (s->timeout_task);
422 s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
423 s->timeout = GNUNET_TIME_UNIT_ZERO_ABS;
424 }
425 if (GNUNET_SCHEDULER_NO_TASK != s->put_disconnect_task)
426 {
427 GNUNET_SCHEDULER_cancel (s->put_disconnect_task);
428 s->put_disconnect_task = GNUNET_SCHEDULER_NO_TASK;
429 }
430 GNUNET_assert (GNUNET_OK ==
431 GNUNET_CONTAINER_multipeermap_remove (plugin->sessions,
432 &s->target,
433 s));
434
435 next = s->msg_head;
436 while (NULL != (pos = next))
437 {
438 next = pos->next;
439 GNUNET_CONTAINER_DLL_remove (s->msg_head,
440 s->msg_tail,
441 pos);
442 GNUNET_assert (0 < s->msgs_in_queue);
443 s->msgs_in_queue--;
444 GNUNET_assert (pos->size <= s->bytes_in_queue);
445 s->bytes_in_queue -= pos->size;
446 if (NULL != pos->transmit_cont)
447 pos->transmit_cont (pos->transmit_cont_cls,
448 &s->target,
449 GNUNET_SYSERR,
450 pos->size,
451 pos->pos + s->overhead);
452 s->overhead = 0;
453 GNUNET_free (pos);
454 }
455 GNUNET_assert (0 == s->msgs_in_queue);
456 GNUNET_assert (0 == s->bytes_in_queue);
457 notify_session_monitor (plugin,
458 s,
459 GNUNET_TRANSPORT_SS_DOWN);
460 if (NULL != s->msg_tk)
461 {
462 GNUNET_SERVER_mst_destroy (s->msg_tk);
463 s->msg_tk = NULL;
464 }
465 GNUNET_HELLO_address_free (s->address);
466 GNUNET_free (s->url);
467 GNUNET_free (s);
468}
469
470
471/**
408 * Increment session timeout due to activity for session @a s. 472 * Increment session timeout due to activity for session @a s.
409 * 473 *
410 * @param s the session 474 * @param s the session
@@ -418,25 +482,85 @@ client_reschedule_session_timeout (struct Session *s)
418 482
419 483
420/** 484/**
485 * Task performing curl operations
486 *
487 * @param cls plugin as closure
488 * @param tc gnunet scheduler task context
489 */
490static void
491client_run (void *cls,
492 const struct GNUNET_SCHEDULER_TaskContext *tc);
493
494
495/**
421 * Function setting up file descriptors and scheduling task to run 496 * Function setting up file descriptors and scheduling task to run
422 * 497 *
423 * @param plugin plugin as closure 498 * @param plugin the plugin as closure
424 * @param now schedule task in 1ms, regardless of what curl may say 499 * @param now schedule task in 1ms, regardless of what curl may say
425 * @return #GNUNET_SYSERR for hard failure, #GNUNET_OK for ok 500 * @return #GNUNET_SYSERR for hard failure, #GNUNET_OK for ok
426 */ 501 */
427static int 502static int
428client_schedule (struct HTTP_Client_Plugin *plugin, 503client_schedule (struct HTTP_Client_Plugin *plugin,
429 int now); 504 int now)
505{
506 fd_set rs;
507 fd_set ws;
508 fd_set es;
509 int max;
510 struct GNUNET_NETWORK_FDSet *grs;
511 struct GNUNET_NETWORK_FDSet *gws;
512 long to;
513 CURLMcode mret;
514 struct GNUNET_TIME_Relative timeout;
430 515
516 /* Cancel previous scheduled task */
517 if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK)
518 {
519 GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
520 plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK;
521 }
522 max = -1;
523 FD_ZERO (&rs);
524 FD_ZERO (&ws);
525 FD_ZERO (&es);
526 mret = curl_multi_fdset (plugin->curl_multi_handle, &rs, &ws, &es, &max);
527 if (mret != CURLM_OK)
528 {
529 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
530 "curl_multi_fdset", __FILE__, __LINE__,
531 curl_multi_strerror (mret));
532 return GNUNET_SYSERR;
533 }
534 mret = curl_multi_timeout (plugin->curl_multi_handle, &to);
535 if (to == -1)
536 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1);
537 else
538 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, to);
539 if (now == GNUNET_YES)
540 timeout = GNUNET_TIME_UNIT_MILLISECONDS;
431 541
432/** 542 if (mret != CURLM_OK)
433 * Connect a HTTP put connection 543 {
434 * 544 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
435 * @param s the session to connect 545 _("%s failed at %s:%d: `%s'\n"),
436 * @return #GNUNET_SYSERR for hard failure, #GNUNET_OK for success 546 "curl_multi_timeout", __FILE__, __LINE__,
437 */ 547 curl_multi_strerror (mret));
438static int 548 return GNUNET_SYSERR;
439client_connect_put (struct Session *s); 549 }
550
551 grs = GNUNET_NETWORK_fdset_create ();
552 gws = GNUNET_NETWORK_fdset_create ();
553 GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
554 GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
555
556 plugin->client_perform_task =
557 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
558 timeout, grs, gws,
559 &client_run, plugin);
560 GNUNET_NETWORK_fdset_destroy (gws);
561 GNUNET_NETWORK_fdset_destroy (grs);
562 return GNUNET_OK;
563}
440 564
441 565
442/** 566/**
@@ -502,6 +626,16 @@ client_log (CURL *curl,
502 626
503 627
504/** 628/**
629 * Connect a HTTP put connection
630 *
631 * @param s the session to connect
632 * @return #GNUNET_SYSERR for hard failure, #GNUNET_OK for success
633 */
634static int
635client_connect_put (struct Session *s);
636
637
638/**
505 * Function that can be used by the transport service to transmit 639 * Function that can be used by the transport service to transmit
506 * a message using the plugin. Note that in the case of a 640 * a message using the plugin. Note that in the case of a
507 * peer disconnecting, the continuation MUST be called 641 * peer disconnecting, the continuation MUST be called
@@ -601,7 +735,7 @@ http_client_plugin_send (void *cls,
601 "Session %p: Reconnecting PUT connection\n", 735 "Session %p: Reconnecting PUT connection\n",
602 s); 736 s);
603 s->put_tmp_disconnected = GNUNET_NO; 737 s->put_tmp_disconnected = GNUNET_NO;
604 GNUNET_break (s->client_put == NULL); 738 GNUNET_break (NULL == s->client_put);
605 if (GNUNET_SYSERR == client_connect_put (s)) 739 if (GNUNET_SYSERR == client_connect_put (s))
606 return GNUNET_SYSERR; 740 return GNUNET_SYSERR;
607 } 741 }
@@ -612,70 +746,6 @@ http_client_plugin_send (void *cls,
612 746
613 747
614/** 748/**
615 * Delete session @a s.
616 *
617 * @param s the session to delete
618 */
619static void
620client_delete_session (struct Session *s)
621{
622 struct HTTP_Client_Plugin *plugin = s->plugin;
623 struct HTTP_Message *pos;
624 struct HTTP_Message *next;
625
626 if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task)
627 {
628 GNUNET_SCHEDULER_cancel (s->timeout_task);
629 s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
630 s->timeout = GNUNET_TIME_UNIT_ZERO_ABS;
631 }
632 if (GNUNET_SCHEDULER_NO_TASK != s->put_disconnect_task)
633 {
634 GNUNET_SCHEDULER_cancel (s->put_disconnect_task);
635 s->put_disconnect_task = GNUNET_SCHEDULER_NO_TASK;
636 }
637 GNUNET_assert (GNUNET_OK ==
638 GNUNET_CONTAINER_multipeermap_remove (plugin->sessions,
639 &s->target,
640 s));
641
642 next = s->msg_head;
643 while (NULL != (pos = next))
644 {
645 next = pos->next;
646 GNUNET_CONTAINER_DLL_remove (s->msg_head,
647 s->msg_tail,
648 pos);
649 GNUNET_assert (0 < s->msgs_in_queue);
650 s->msgs_in_queue--;
651 GNUNET_assert (pos->size <= s->bytes_in_queue);
652 s->bytes_in_queue -= pos->size;
653 if (NULL != pos->transmit_cont)
654 pos->transmit_cont (pos->transmit_cont_cls,
655 &s->target,
656 GNUNET_SYSERR,
657 pos->size,
658 pos->pos + s->overhead);
659 s->overhead = 0;
660 GNUNET_free (pos);
661 }
662 GNUNET_assert (0 == s->msgs_in_queue);
663 GNUNET_assert (0 == s->bytes_in_queue);
664 notify_session_monitor (plugin,
665 s,
666 GNUNET_TRANSPORT_SS_DOWN);
667 if (NULL != s->msg_tk)
668 {
669 GNUNET_SERVER_mst_destroy (s->msg_tk);
670 s->msg_tk = NULL;
671 }
672 GNUNET_HELLO_address_free (s->address);
673 GNUNET_free (s->url);
674 GNUNET_free (s);
675}
676
677
678/**
679 * Disconnect a session 749 * Disconnect a session
680 * 750 *
681 * @param cls the `struct HTTP_Client_Plugin *` 751 * @param cls the `struct HTTP_Client_Plugin *`
@@ -701,7 +771,8 @@ http_client_plugin_session_disconnect (void *cls,
701 GNUNET_i2s (&s->target)); 771 GNUNET_i2s (&s->target));
702 772
703 /* remove curl handle from multi handle */ 773 /* remove curl handle from multi handle */
704 mret = curl_multi_remove_handle (plugin->curl_multi_handle, s->client_put); 774 mret = curl_multi_remove_handle (plugin->curl_multi_handle,
775 s->client_put);
705 if (mret != CURLM_OK) 776 if (mret != CURLM_OK)
706 { 777 {
707 /* clean up easy handle, handle is now invalid and free'd */ 778 /* clean up easy handle, handle is now invalid and free'd */
@@ -1203,88 +1274,6 @@ client_receive (void *stream,
1203 * Task performing curl operations 1274 * Task performing curl operations
1204 * 1275 *
1205 * @param cls plugin as closure 1276 * @param cls plugin as closure
1206 * @param tc gnunet scheduler task context
1207 */
1208static void
1209client_run (void *cls,
1210 const struct GNUNET_SCHEDULER_TaskContext *tc);
1211
1212
1213/**
1214 * Function setting up file descriptors and scheduling task to run
1215 *
1216 * @param plugin the plugin as closure
1217 * @param now schedule task in 1ms, regardless of what curl may say
1218 * @return #GNUNET_SYSERR for hard failure, #GNUNET_OK for ok
1219 */
1220static int
1221client_schedule (struct HTTP_Client_Plugin *plugin,
1222 int now)
1223{
1224 fd_set rs;
1225 fd_set ws;
1226 fd_set es;
1227 int max;
1228 struct GNUNET_NETWORK_FDSet *grs;
1229 struct GNUNET_NETWORK_FDSet *gws;
1230 long to;
1231 CURLMcode mret;
1232 struct GNUNET_TIME_Relative timeout;
1233
1234 /* Cancel previous scheduled task */
1235 if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK)
1236 {
1237 GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
1238 plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK;
1239 }
1240 max = -1;
1241 FD_ZERO (&rs);
1242 FD_ZERO (&ws);
1243 FD_ZERO (&es);
1244 mret = curl_multi_fdset (plugin->curl_multi_handle, &rs, &ws, &es, &max);
1245 if (mret != CURLM_OK)
1246 {
1247 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
1248 "curl_multi_fdset", __FILE__, __LINE__,
1249 curl_multi_strerror (mret));
1250 return GNUNET_SYSERR;
1251 }
1252 mret = curl_multi_timeout (plugin->curl_multi_handle, &to);
1253 if (to == -1)
1254 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1);
1255 else
1256 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, to);
1257 if (now == GNUNET_YES)
1258 timeout = GNUNET_TIME_UNIT_MILLISECONDS;
1259
1260 if (mret != CURLM_OK)
1261 {
1262 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1263 _("%s failed at %s:%d: `%s'\n"),
1264 "curl_multi_timeout", __FILE__, __LINE__,
1265 curl_multi_strerror (mret));
1266 return GNUNET_SYSERR;
1267 }
1268
1269 grs = GNUNET_NETWORK_fdset_create ();
1270 gws = GNUNET_NETWORK_fdset_create ();
1271 GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
1272 GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
1273
1274 plugin->client_perform_task =
1275 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1276 timeout, grs, gws,
1277 &client_run, plugin);
1278 GNUNET_NETWORK_fdset_destroy (gws);
1279 GNUNET_NETWORK_fdset_destroy (grs);
1280 return GNUNET_OK;
1281}
1282
1283
1284/**
1285 * Task performing curl operations
1286 *
1287 * @param cls plugin as closure
1288 * @param tc scheduler task context 1277 * @param tc scheduler task context
1289 */ 1278 */
1290static void 1279static void
@@ -1369,12 +1358,12 @@ client_run (void *cls,
1369 */ 1358 */
1370 if (GNUNET_YES == s->put_reconnect_required) 1359 if (GNUNET_YES == s->put_reconnect_required)
1371 { 1360 {
1372 s->put_reconnect_required = GNUNET_NO; 1361 s->put_reconnect_required = GNUNET_NO;
1373 if (GNUNET_SYSERR == client_connect_put(s)) 1362 if (GNUNET_SYSERR == client_connect_put (s))
1374 { 1363 {
1375 GNUNET_break (s->client_put == NULL); 1364 GNUNET_break (s->client_put == NULL);
1376 GNUNET_break (s->put_tmp_disconnected == GNUNET_NO); 1365 GNUNET_break (s->put_tmp_disconnected == GNUNET_NO);
1377 } 1366 }
1378 } 1367 }
1379 } 1368 }
1380 if (easy_h == s->client_get) 1369 if (easy_h == s->client_get)
@@ -2171,7 +2160,6 @@ http_client_plugin_setup_monitor (void *cls,
2171} 2160}
2172 2161
2173 2162
2174
2175/** 2163/**
2176 * Entry point for the plugin. 2164 * Entry point for the plugin.
2177 */ 2165 */