aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_http_client.c
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2012-08-24 15:18:41 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2012-08-24 15:18:41 +0000
commitffd9b2ac043fa379e2d289ef1a7bc9d281de92b1 (patch)
treec93983cf01271c8a866d2edb5b4ee4edd0d5fff5 /src/transport/plugin_transport_http_client.c
parent3f70e71b5e73cb6464bcdccdc69be22cfbc3af69 (diff)
downloadgnunet-ffd9b2ac043fa379e2d289ef1a7bc9d281de92b1.tar.gz
gnunet-ffd9b2ac043fa379e2d289ef1a7bc9d281de92b1.zip
changes to address notification
Diffstat (limited to 'src/transport/plugin_transport_http_client.c')
-rw-r--r--src/transport/plugin_transport_http_client.c305
1 files changed, 196 insertions, 109 deletions
diff --git a/src/transport/plugin_transport_http_client.c b/src/transport/plugin_transport_http_client.c
index ff148c2a6..15b6729f4 100644
--- a/src/transport/plugin_transport_http_client.c
+++ b/src/transport/plugin_transport_http_client.c
@@ -546,10 +546,181 @@ client_receive (void *stream, size_t size, size_t nmemb, void *cls)
546 * @param tc gnunet scheduler task context 546 * @param tc gnunet scheduler task context
547 */ 547 */
548static void 548static void
549client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
550
551/**
552 * Function setting up file descriptors and scheduling task to run
553 *
554 * @param plugin plugin as closure
555 * @param now schedule task in 1ms, regardless of what curl may say
556 * @return GNUNET_SYSERR for hard failure, GNUNET_OK for ok
557 */
558static int
559client_schedule (struct HTTP_Client_Plugin *plugin, int now)
560{
561 fd_set rs;
562 fd_set ws;
563 fd_set es;
564 int max;
565 struct GNUNET_NETWORK_FDSet *grs;
566 struct GNUNET_NETWORK_FDSet *gws;
567 long to;
568 CURLMcode mret;
569 struct GNUNET_TIME_Relative timeout;
570
571 /* Cancel previous scheduled task */
572 if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK)
573 {
574 GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
575 plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK;
576 }
577 max = -1;
578 FD_ZERO (&rs);
579 FD_ZERO (&ws);
580 FD_ZERO (&es);
581 mret = curl_multi_fdset (plugin->curl_multi_handle, &rs, &ws, &es, &max);
582 if (mret != CURLM_OK)
583 {
584 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
585 "curl_multi_fdset", __FILE__, __LINE__,
586 curl_multi_strerror (mret));
587 return GNUNET_SYSERR;
588 }
589 mret = curl_multi_timeout (plugin->curl_multi_handle, &to);
590 if (to == -1)
591 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1);
592 else
593 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, to);
594 if (now == GNUNET_YES)
595 timeout = GNUNET_TIME_UNIT_MILLISECONDS;
596
597 if (mret != CURLM_OK)
598 {
599 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
600 "curl_multi_timeout", __FILE__, __LINE__,
601 curl_multi_strerror (mret));
602 return GNUNET_SYSERR;
603 }
604
605 grs = GNUNET_NETWORK_fdset_create ();
606 gws = GNUNET_NETWORK_fdset_create ();
607 GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
608 GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
609
610 plugin->client_perform_task =
611 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
612 timeout, grs, gws,
613 &client_run, plugin);
614 GNUNET_NETWORK_fdset_destroy (gws);
615 GNUNET_NETWORK_fdset_destroy (grs);
616 return GNUNET_OK;
617}
618
619
620
621static int
622client_disconnect (struct Session *s)
623{
624
625 int res = GNUNET_OK;
626 CURLMcode mret;
627 struct HTTP_Client_Plugin *plugin = s->plugin;
628 struct HTTP_Message *msg;
629 struct HTTP_Message *t;
630
631 if (GNUNET_YES != client_exist_session (plugin, s))
632 {
633 GNUNET_break (0);
634 return GNUNET_SYSERR;
635 }
636
637 if (s->client_put != NULL)
638 {
639 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
640 "Client: %p / %p Deleting outbound PUT session to peer `%s'\n",
641 s, s->client_put, GNUNET_i2s (&s->target));
642
643 /* remove curl handle from multi handle */
644 mret = curl_multi_remove_handle (plugin->curl_multi_handle, s->client_put);
645 if (mret != CURLM_OK)
646 {
647 /* clean up easy handle, handle is now invalid and free'd */
648 res = GNUNET_SYSERR;
649 GNUNET_break (0);
650 }
651 curl_easy_cleanup (s->client_put);
652 s->client_put = NULL;
653 }
654
655
656 if (s->recv_wakeup_task != GNUNET_SCHEDULER_NO_TASK)
657 {
658 GNUNET_SCHEDULER_cancel (s->recv_wakeup_task);
659 s->recv_wakeup_task = GNUNET_SCHEDULER_NO_TASK;
660 }
661
662 if (s->client_get != NULL)
663 {
664 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
665 "Client: %p / %p Deleting outbound GET session to peer `%s'\n",
666 s,
667 s->client_get, GNUNET_i2s (&s->target));
668
669 /* remove curl handle from multi handle */
670 mret = curl_multi_remove_handle (plugin->curl_multi_handle, s->client_get);
671 if (mret != CURLM_OK)
672 {
673 /* clean up easy handle, handle is now invalid and free'd */
674 res = GNUNET_SYSERR;
675 GNUNET_break (0);
676 }
677 curl_easy_cleanup (s->client_get);
678 s->client_get = NULL;
679 }
680
681 msg = s->msg_head;
682 while (msg != NULL)
683 {
684 t = msg->next;
685 if (NULL != msg->transmit_cont)
686 msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR);
687 GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
688 GNUNET_free (msg);
689 msg = t;
690 }
691
692 plugin->cur_connections -= 2;
693 plugin->env->session_end (plugin->env->cls, &s->target, s);
694
695 GNUNET_assert (plugin->cur_connections > 0);
696 plugin->cur_connections --;
697 GNUNET_STATISTICS_set (plugin->env->stats,
698 "# HTTP client connections",
699 plugin->cur_connections,
700 GNUNET_NO);
701
702 /* Re-schedule since handles have changed */
703 if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK)
704 {
705 GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
706 plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK;
707 }
708 client_schedule (plugin, GNUNET_YES);
709
710 return res;
711}
712
713
714/**
715 * Task performing curl operations
716 *
717 * @param cls plugin as closure
718 * @param tc gnunet scheduler task context
719 */
720static void
549client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 721client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
550{ 722{
551 GNUNET_break (0); 723 GNUNET_break (0);
552#if 0
553 struct HTTP_Client_Plugin *plugin = cls; 724 struct HTTP_Client_Plugin *plugin = cls;
554 int running; 725 int running;
555 CURLMcode mret; 726 CURLMcode mret;
@@ -563,12 +734,12 @@ client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
563 do 734 do
564 { 735 {
565 running = 0; 736 running = 0;
566 mret = curl_multi_perform (plugin->client_mh, &running); 737 mret = curl_multi_perform (plugin->curl_multi_handle, &running);
567 738
568 CURLMsg *msg; 739 CURLMsg *msg;
569 int msgs_left; 740 int msgs_left;
570 741
571 while ((msg = curl_multi_info_read (plugin->client_mh, &msgs_left))) 742 while ((msg = curl_multi_info_read (plugin->curl_multi_handle, &msgs_left)))
572 { 743 {
573 CURL *easy_h = msg->easy_handle; 744 CURL *easy_h = msg->easy_handle;
574 struct Session *s = NULL; 745 struct Session *s = NULL;
@@ -588,7 +759,7 @@ client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
588 curl_easy_getinfo (easy_h, CURLINFO_PRIVATE, &d)); 759 curl_easy_getinfo (easy_h, CURLINFO_PRIVATE, &d));
589 s = (struct Session *) d; 760 s = (struct Session *) d;
590 761
591 if (GNUNET_YES != exist_session(plugin, s)) 762 if (GNUNET_YES != client_exist_session(plugin, s))
592 { 763 {
593 GNUNET_break (0); 764 GNUNET_break (0);
594 return; 765 return;
@@ -600,7 +771,7 @@ client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
600 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, 771 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
601 "Client: %p connection to '%s' %s ended with reason %i: `%s'\n", 772 "Client: %p connection to '%s' %s ended with reason %i: `%s'\n",
602 msg->easy_handle, GNUNET_i2s (&s->target), 773 msg->easy_handle, GNUNET_i2s (&s->target),
603 http_plugin_address_to_string (NULL, s->addr, 774 http_common_plugin_address_to_string (NULL, s->addr,
604 s->addrlen), 775 s->addrlen),
605 msg->data.result, 776 msg->data.result,
606 curl_easy_strerror (msg->data.result)); 777 curl_easy_strerror (msg->data.result));
@@ -612,7 +783,6 @@ client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
612 } 783 }
613 while (mret == CURLM_CALL_MULTI_PERFORM); 784 while (mret == CURLM_CALL_MULTI_PERFORM);
614 client_schedule (plugin, GNUNET_NO); 785 client_schedule (plugin, GNUNET_NO);
615#endif
616} 786}
617 787
618 788
@@ -848,102 +1018,6 @@ client_start (struct HTTP_Client_Plugin *plugin)
848 return GNUNET_OK; 1018 return GNUNET_OK;
849} 1019}
850 1020
851static int
852client_disconnect (struct Session *s)
853{
854#if 0
855 int res = GNUNET_OK;
856 CURLMcode mret;
857 struct Plugin *plugin = s->plugin;
858 struct HTTP_Message *msg;
859 struct HTTP_Message *t;
860
861 if (GNUNET_YES != exist_session(plugin, s))
862 {
863 GNUNET_break (0);
864 return GNUNET_SYSERR;
865 }
866
867 if (s->client_put != NULL)
868 {
869 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
870 "Client: %p / %p Deleting outbound PUT session to peer `%s'\n",
871 s, s->client_put, GNUNET_i2s (&s->target));
872
873 /* remove curl handle from multi handle */
874 mret = curl_multi_remove_handle (plugin->client_mh, s->client_put);
875 if (mret != CURLM_OK)
876 {
877 /* clean up easy handle, handle is now invalid and free'd */
878 res = GNUNET_SYSERR;
879 GNUNET_break (0);
880 }
881 curl_easy_cleanup (s->client_put);
882 s->client_put = NULL;
883 }
884
885
886 if (s->recv_wakeup_task != GNUNET_SCHEDULER_NO_TASK)
887 {
888 GNUNET_SCHEDULER_cancel (s->recv_wakeup_task);
889 s->recv_wakeup_task = GNUNET_SCHEDULER_NO_TASK;
890 }
891
892 if (s->client_get != NULL)
893 {
894 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
895 "Client: %p / %p Deleting outbound GET session to peer `%s'\n",
896 s,
897 s->client_get, GNUNET_i2s (&s->target));
898
899 /* remove curl handle from multi handle */
900 mret = curl_multi_remove_handle (plugin->client_mh, s->client_get);
901 if (mret != CURLM_OK)
902 {
903 /* clean up easy handle, handle is now invalid and free'd */
904 res = GNUNET_SYSERR;
905 GNUNET_break (0);
906 }
907 curl_easy_cleanup (s->client_get);
908 s->client_get = NULL;
909 }
910
911 msg = s->msg_head;
912 while (msg != NULL)
913 {
914 t = msg->next;
915 if (NULL != msg->transmit_cont)
916 msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR);
917 GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
918 GNUNET_free (msg);
919 msg = t;
920 }
921
922 plugin->cur_connections -= 2;
923
924 notify_session_end (plugin, &s->target, s);
925
926 GNUNET_assert (plugin->outbound_sessions > 0);
927 plugin->outbound_sessions --;
928 GNUNET_STATISTICS_set (plugin->env->stats,
929 "# HTTP outbound sessions",
930 plugin->outbound_sessions,
931 GNUNET_NO);
932
933 /* Re-schedule since handles have changed */
934 if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK)
935 {
936 GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
937 plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK;
938 }
939 client_schedule (plugin, GNUNET_YES);
940
941 return res;
942#endif
943 GNUNET_break (0);
944 return 0;
945}
946
947/** 1021/**
948 * Session was idle, so disconnect it 1022 * Session was idle, so disconnect it
949 */ 1023 */
@@ -986,18 +1060,17 @@ client_start_session_timeout (struct Session *s)
986static void 1060static void
987client_reschedule_session_timeout (struct Session *s) 1061client_reschedule_session_timeout (struct Session *s)
988{ 1062{
989#if 0 1063
990 GNUNET_assert (NULL != s); 1064 GNUNET_assert (NULL != s);
991 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task); 1065 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task);
992 1066
993 GNUNET_SCHEDULER_cancel (s->timeout_task); 1067 GNUNET_SCHEDULER_cancel (s->timeout_task);
994 s->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, 1068 s->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
995 &server_session_timeout, 1069 &client_session_timeout,
996 s); 1070 s);
997 GNUNET_log (TIMEOUT_LOG, 1071 GNUNET_log (TIMEOUT_LOG,
998 "Timeout rescheduled for session %p set to %llu ms\n", 1072 "Timeout rescheduled for session %p set to %llu ms\n",
999 s, (unsigned long long) TIMEOUT.rel_value); 1073 s, (unsigned long long) TIMEOUT.rel_value);
1000#endif
1001 GNUNET_break (0); 1074 GNUNET_break (0);
1002} 1075}
1003 1076
@@ -1048,6 +1121,12 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
1048 struct GNUNET_TRANSPORT_PluginFunctions *api = cls; 1121 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1049 struct HTTP_Client_Plugin *plugin = api->cls; 1122 struct HTTP_Client_Plugin *plugin = api->cls;
1050 1123
1124 if (NULL == api->cls)
1125 {
1126 GNUNET_free (api);
1127 return NULL;
1128 }
1129
1051 if (NULL != plugin->curl_multi_handle) 1130 if (NULL != plugin->curl_multi_handle)
1052 { 1131 {
1053 curl_multi_cleanup (plugin->curl_multi_handle); 1132 curl_multi_cleanup (plugin->curl_multi_handle);
@@ -1071,6 +1150,18 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
1071 struct GNUNET_TRANSPORT_PluginFunctions *api; 1150 struct GNUNET_TRANSPORT_PluginFunctions *api;
1072 struct HTTP_Client_Plugin *plugin; 1151 struct HTTP_Client_Plugin *plugin;
1073 1152
1153 if (NULL == env->receive)
1154 {
1155 /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
1156 initialze the plugin or the API */
1157 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1158 api->cls = NULL;
1159 api->address_to_string = &http_common_plugin_address_to_string;
1160 api->string_to_address = &http_common_plugin_string_to_address;
1161 api->address_pretty_printer = &http_common_plugin_address_pretty_printer;
1162 return api;
1163 }
1164
1074 plugin = GNUNET_malloc (sizeof (struct HTTP_Client_Plugin)); 1165 plugin = GNUNET_malloc (sizeof (struct HTTP_Client_Plugin));
1075 p = plugin; 1166 p = plugin;
1076 plugin->env = env; 1167 plugin->env = env;
@@ -1081,10 +1172,6 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
1081 api->check_address = &http_client_plugin_address_suggested; 1172 api->check_address = &http_client_plugin_address_suggested;
1082 api->get_session = &http_client_plugin_get_session; 1173 api->get_session = &http_client_plugin_get_session;
1083 1174
1084 api->address_to_string = &http_common_plugin_address_to_string;
1085 api->string_to_address = &http_common_plugin_string_to_address;
1086 api->address_pretty_printer = &http_common_plugin_address_pretty_printer;
1087
1088#if BUILD_HTTPS 1175#if BUILD_HTTPS
1089 plugin->name = "transport-https_client"; 1176 plugin->name = "transport-https_client";
1090 plugin->protocol = "https"; 1177 plugin->protocol = "https";