GNUnet  0.10.x
plugin_transport_http_client.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2002-2014 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 
28 #if BUILD_HTTPS
29 #define PLUGIN_NAME "https_client"
30 #define HTTP_STAT_STR_CONNECTIONS "# HTTPS client connections"
31 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_https_client_init
32 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_https_client_done
33 #else
34 #define PLUGIN_NAME "http_client"
35 #define HTTP_STAT_STR_CONNECTIONS "# HTTP client connections"
36 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_http_client_init
37 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_client_done
38 #endif
39 
40 #define VERBOSE_CURL GNUNET_NO
41 
42 #define PUT_DISCONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
43 
44 #define ENABLE_PUT GNUNET_YES
45 #define ENABLE_GET GNUNET_YES
46 
47 #include "platform.h"
48 #include "gnunet_util_lib.h"
49 #include "gnunet_protocols.h"
52 /* Just included for the right curl.h */
53 #include "gnunet_curl_lib.h"
54 
55 
56 #define LOG(kind,...) GNUNET_log_from(kind, PLUGIN_NAME, __VA_ARGS__)
57 
61 struct HTTP_Client_Plugin;
62 
67 {
72 
77 
82 
87 
92 
97 
102 };
103 
107 struct HTTP_Message
108 {
112  struct HTTP_Message *next;
113 
117  struct HTTP_Message *prev;
118 
122  char *buf;
123 
130 
134  void *transmit_cont_cls;
135 
139  size_t pos;
140 
144  size_t size;
145 
146 };
147 
148 
152 struct GNUNET_ATS_Session;
153 
154 
159 struct RequestHandle
160 {
165 
169  CURL *easyhandle;
170 
175 };
176 
177 
181 struct GNUNET_ATS_Session
182 {
186  char *url;
187 
192 
197 
201  struct RequestHandle put;
202 
206  struct RequestHandle get;
207 
211  struct HTTP_Message *msg_head;
212 
216  struct HTTP_Message *msg_tail;
217 
222 
227 
232 
236  struct GNUNET_SCHEDULER_Task *recv_wakeup_task;
237 
242  struct GNUNET_TIME_Absolute next_receive;
243 
248 
252  unsigned long long bytes_in_queue;
253 
258  size_t overhead;
259 
263  unsigned int msgs_in_queue;
264 
269 };
270 
271 
276 {
281 
286 
291 
295  void *sic_cls;
296 
300  char *name;
301 
305  char *protocol;
306 
311 
316 
321 
326 
331 
339  curl_proxytype proxytype;
340 
349 
353  uint32_t options;
354 
359  unsigned int max_requests;
360 
365  unsigned int cur_requests;
366 
370  uint32_t last_tag;
371 
375  uint16_t use_ipv6;
376 
380  uint16_t use_ipv4;
381 
386 };
387 
388 
396 static int
398 
399 
408 static void
410  struct GNUNET_ATS_Session *session,
412 {
413  struct GNUNET_TRANSPORT_SessionInfo info;
414 
415  if (NULL == plugin->sic)
416  return;
417  memset (&info, 0, sizeof (info));
418  info.state = state;
419  info.is_inbound = GNUNET_NO;
420  info.num_msg_pending = session->msgs_in_queue;
421  info.num_bytes_pending = session->bytes_in_queue;
422  info.receive_delay = session->next_receive;
423  info.session_timeout = session->timeout;
424  info.address = session->address;
425  plugin->sic (plugin->sic_cls,
426  session,
427  &info);
428 }
429 
430 
436 static void
438 {
439  struct HTTP_Client_Plugin *plugin = s->plugin;
440  struct HTTP_Message *pos;
441  struct HTTP_Message *next;
442  CURLMcode mret;
443 
444  if (NULL != s->timeout_task)
445  {
447  s->timeout_task = NULL;
449  }
450  if (NULL != s->put_disconnect_task)
451  {
453  s->put_disconnect_task = NULL;
454  }
455  if (NULL != s->recv_wakeup_task)
456  {
458  s->recv_wakeup_task = NULL;
459  }
462  &s->address->peer,
463  s));
464  if (NULL != s->put.easyhandle)
465  {
467  "Session %p/request %p: disconnecting PUT request to peer `%s'\n",
468  s,
469  s->put.easyhandle,
470  GNUNET_i2s (&s->address->peer));
471 
472  /* remove curl handle from multi handle */
473  mret = curl_multi_remove_handle (plugin->curl_multi_handle,
474  s->put.easyhandle);
475  GNUNET_break (CURLM_OK == mret);
476  curl_easy_cleanup (s->put.easyhandle);
477  GNUNET_assert (plugin->cur_requests > 0);
478  plugin->cur_requests--;
479  s->put.easyhandle = NULL;
480  }
481  if (NULL != s->get.easyhandle)
482  {
484  "Session %p/request %p: disconnecting GET request to peer `%s'\n",
485  s, s->get.easyhandle,
486  GNUNET_i2s (&s->address->peer));
487  /* remove curl handle from multi handle */
488  mret = curl_multi_remove_handle (plugin->curl_multi_handle,
489  s->get.easyhandle);
490  GNUNET_break (CURLM_OK == mret);
491  curl_easy_cleanup (s->get.easyhandle);
492  GNUNET_assert (plugin->cur_requests > 0);
493  plugin->cur_requests--;
494  s->get.easyhandle = NULL;
495  }
496 
497  GNUNET_STATISTICS_set (plugin->env->stats,
499  plugin->cur_requests,
500  GNUNET_NO);
501  next = s->msg_head;
502  while (NULL != (pos = next))
503  {
504  next = pos->next;
506  s->msg_tail,
507  pos);
508  GNUNET_assert (0 < s->msgs_in_queue);
509  s->msgs_in_queue--;
510  GNUNET_assert (pos->size <= s->bytes_in_queue);
511  s->bytes_in_queue -= pos->size;
512  if (NULL != pos->transmit_cont)
513  pos->transmit_cont (pos->transmit_cont_cls,
514  &s->address->peer,
516  pos->size,
517  pos->pos + s->overhead);
518  s->overhead = 0;
519  GNUNET_free (pos);
520  }
521  GNUNET_assert (0 == s->msgs_in_queue);
522  GNUNET_assert (0 == s->bytes_in_queue);
523  notify_session_monitor (plugin,
524  s,
526  if (NULL != s->msg_tk)
527  {
529  s->msg_tk = NULL;
530  }
532  GNUNET_free (s->url);
533  GNUNET_free (s);
534 }
535 
536 
542 static void
544 {
545  GNUNET_assert (NULL != s->timeout_task);
547 }
548 
549 
556 static void
557 client_run (void *cls);
558 
559 
567 static int
569  int now)
570 {
571  fd_set rs;
572  fd_set ws;
573  fd_set es;
574  int max;
575  struct GNUNET_NETWORK_FDSet *grs;
576  struct GNUNET_NETWORK_FDSet *gws;
577  long to;
578  CURLMcode mret;
579  struct GNUNET_TIME_Relative timeout;
580 
581  /* Cancel previous scheduled task */
582  if (plugin->client_perform_task != NULL)
583  {
585  plugin->client_perform_task = NULL;
586  }
587  max = -1;
588  FD_ZERO (&rs);
589  FD_ZERO (&ws);
590  FD_ZERO (&es);
591  mret = curl_multi_fdset (plugin->curl_multi_handle, &rs, &ws, &es, &max);
592  if (mret != CURLM_OK)
593  {
595  _("%s failed at %s:%d: `%s'\n"),
596  "curl_multi_fdset",
597  __FILE__,
598  __LINE__,
599  curl_multi_strerror (mret));
600  return GNUNET_SYSERR;
601  }
602  mret = curl_multi_timeout (plugin->curl_multi_handle, &to);
603  if (-1 == to)
605  else
607  if (now == GNUNET_YES)
609 
610  if (CURLM_OK != mret)
611  {
613  _("%s failed at %s:%d: `%s'\n"),
614  "curl_multi_timeout", __FILE__, __LINE__,
615  curl_multi_strerror (mret));
616  return GNUNET_SYSERR;
617  }
618 
621  GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
622  GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
623 
624  /* Schedule task to run when select is ready to read or write */
625  plugin->client_perform_task =
627  timeout, grs, gws,
628  &client_run, plugin);
631  return GNUNET_OK;
632 }
633 
634 
635 #if VERBOSE_CURL
636 
646 static int
647 client_log (CURL *curl,
648  curl_infotype type,
649  const char *data,
650  size_t size,
651  void *cls)
652 {
653  struct RequestHandle *ch = cls;
654  const char *ttype = "UNSPECIFIED";
655  char text[size + 2];
656 
657  if (! ((CURLINFO_TEXT == type) ||
658  (CURLINFO_HEADER_IN == type) ||
659  (CURLINFO_HEADER_OUT == type)))
660  return 0;
661  switch (type)
662  {
663  case CURLINFO_TEXT:
664  ttype = "TEXT";
665  break;
666  case CURLINFO_HEADER_IN:
667  ttype = "HEADER_IN";
668  break;
669  case CURLINFO_HEADER_OUT:
670  ttype = "HEADER_OUT";
671  /* Overhead*/
672  GNUNET_assert (NULL != ch);
673  GNUNET_assert (NULL != ch->easyhandle);
674  GNUNET_assert (NULL != ch->s);
675  ch->s->overhead += size;
676  break;
677  default:
678  ttype = "UNSPECIFIED";
679  break;
680  }
681  GNUNET_memcpy (text, data, size);
682  if (text[size - 1] == '\n')
683  {
684  text[size] = '\0';
685  }
686  else
687  {
688  text[size] = '\n';
689  text[size + 1] = '\0';
690  }
692  "Request %p %s: %s",
693  ch->easyhandle,
694  ttype,
695  text);
696  return 0;
697 }
698 #endif
699 
706 static int
708 
709 
716 static int
718 
719 
747 static ssize_t
749  struct GNUNET_ATS_Session *s,
750  const char *msgbuf,
751  size_t msgbuf_size,
752  unsigned int priority,
753  struct GNUNET_TIME_Relative to,
755  void *cont_cls)
756 {
757  struct HTTP_Client_Plugin *plugin = cls;
758  struct HTTP_Message *msg;
759  char *stat_txt;
760 
762  "Session %p/request %p: Sending message with %u to peer `%s' \n",
763  s,
764  s->put.easyhandle,
765  msgbuf_size,
766  GNUNET_i2s (&s->address->peer));
767 
768  /* create new message and schedule */
769  msg = GNUNET_malloc (sizeof (struct HTTP_Message) + msgbuf_size);
770  msg->size = msgbuf_size;
771  msg->buf = (char *) &msg[1];
772  msg->transmit_cont = cont;
773  msg->transmit_cont_cls = cont_cls;
774  GNUNET_memcpy (msg->buf,
775  msgbuf,
776  msgbuf_size);
778  s->msg_tail,
779  msg);
780  s->msgs_in_queue++;
781  s->bytes_in_queue += msg->size;
782 
783  GNUNET_asprintf (&stat_txt,
784  "# bytes currently in %s_client buffers",
785  plugin->protocol);
787  stat_txt, msgbuf_size, GNUNET_NO);
788  GNUNET_free (stat_txt);
789  notify_session_monitor (plugin,
790  s,
792  if (H_TMP_DISCONNECTING == s->put.state)
793  {
794  /* PUT request is currently getting disconnected */
797  "Session %p/request %p: currently disconnecting, reconnecting immediately\n",
798  s,
799  s->put.easyhandle);
800  return msgbuf_size;
801  }
802  if (H_PAUSED == s->put.state)
803  {
804  /* PUT request was paused, unpause */
805  GNUNET_assert (s->put_disconnect_task != NULL);
807  s->put_disconnect_task = NULL;
809  "Session %p/request %p: unpausing request\n",
810  s, s->put.easyhandle);
811  s->put.state = H_CONNECTED;
812  if (NULL != s->put.easyhandle)
813  curl_easy_pause (s->put.easyhandle, CURLPAUSE_CONT);
814  }
815  else if (H_TMP_DISCONNECTED == s->put.state)
816  {
817  /* PUT request was disconnected, reconnect */
818  LOG (GNUNET_ERROR_TYPE_DEBUG, "Session %p: Reconnecting PUT request\n", s);
819  GNUNET_break (NULL == s->put.easyhandle);
821  {
822  /* Could not reconnect */
824  return GNUNET_SYSERR;
825  }
826  }
828  return msgbuf_size;
829 }
830 
831 
839 static int
841  struct GNUNET_ATS_Session *s)
842 {
843  struct HTTP_Client_Plugin *plugin = cls;
844 
846  "Session %p: notifying transport about ending session\n",
847  s);
848  plugin->env->session_end (plugin->env->cls,
849  s->address,
850  s);
852 
853  /* Re-schedule since handles have changed */
854  if (NULL != plugin->client_perform_task)
855  {
857  plugin->client_perform_task = NULL;
858  }
859  client_schedule (plugin, GNUNET_YES);
860 
861  return GNUNET_OK;
862 }
863 
864 
873 static unsigned int
875 {
876  return 3;
877 }
878 
879 
888 static int
890  const struct GNUNET_PeerIdentity *peer,
891  void *value)
892 {
893  struct HTTP_Client_Plugin *plugin = cls;
894  struct GNUNET_ATS_Session *session = value;
895 
896  http_client_plugin_session_disconnect (plugin, session);
897  return GNUNET_OK;
898 }
899 
900 
909 static void
911  const struct GNUNET_PeerIdentity *target)
912 {
913  struct HTTP_Client_Plugin *plugin = cls;
914 
916  "Transport tells me to disconnect `%s'\n",
917  GNUNET_i2s (target));
919  target,
921  plugin);
922 }
923 
924 
929 {
934 
939 };
940 
941 
950 static int
952  const struct GNUNET_PeerIdentity *key,
953  void *value)
954 {
955  struct GNUNET_ATS_SessionClientCtx *sc_ctx = cls;
956  struct GNUNET_ATS_Session *s = value;
957 
958  if (0 == GNUNET_HELLO_address_cmp (sc_ctx->address,
959  s->address))
960  {
961  sc_ctx->ret = s;
962  return GNUNET_NO;
963  }
964  return GNUNET_YES;
965 }
966 
967 
975 static struct GNUNET_ATS_Session *
977  const struct GNUNET_HELLO_Address *address)
978 {
979  struct GNUNET_ATS_SessionClientCtx sc_ctx;
980 
981  sc_ctx.address = address;
982  sc_ctx.ret = NULL;
985  &sc_ctx);
986  return sc_ctx.ret;
987 }
988 
989 
997 static void
999 {
1000  struct GNUNET_ATS_Session *s = cls;
1001 
1002  s->put_disconnect_task = NULL;
1004  "Session %p/request %p: will be disconnected due to no activity\n",
1005  s, s->put.easyhandle);
1007  if (NULL != s->put.easyhandle)
1008  curl_easy_pause (s->put.easyhandle,
1009  CURLPAUSE_CONT);
1011 }
1012 
1013 
1024 static size_t
1025 client_send_cb (void *stream,
1026  size_t size,
1027  size_t nmemb,
1028  void *cls)
1029 {
1030  struct GNUNET_ATS_Session *s = cls;
1031  struct HTTP_Client_Plugin *plugin = s->plugin;
1032  struct HTTP_Message *msg = s->msg_head;
1033  size_t len;
1034  char *stat_txt;
1035 
1036  if (H_TMP_DISCONNECTING == s->put.state)
1037  {
1039  "Session %p/request %p: disconnect due to inactivity\n",
1040  s, s->put.easyhandle);
1041  return 0;
1042  }
1043 
1044  if (NULL == msg)
1045  {
1046  if (GNUNET_YES == plugin->emulate_xhr)
1047  {
1049  "Session %p/request %p: PUT request finished\n",
1050  s,
1051  s->put.easyhandle);
1053  return 0;
1054  }
1055 
1056  /* We have nothing to send, so pause PUT request */
1058  "Session %p/request %p: nothing to send, suspending\n",
1059  s,
1060  s->put.easyhandle);
1064  s);
1065  s->put.state = H_PAUSED;
1066  return CURL_READFUNC_PAUSE;
1067  }
1068  /* data to send */
1069  GNUNET_assert (msg->pos < msg->size);
1070  /* calculate how much fits in buffer */
1071  len = GNUNET_MIN (msg->size - msg->pos,
1072  size * nmemb);
1073  GNUNET_memcpy (stream,
1074  &msg->buf[msg->pos],
1075  len);
1076  msg->pos += len;
1077  if (msg->pos == msg->size)
1078  {
1080  "Session %p/request %p: sent message with %u bytes sent, removing message from queue\n",
1081  s,
1082  s->put.easyhandle,
1083  msg->size,
1084  msg->pos);
1085  /* Calling transmit continuation */
1087  s->msg_tail,
1088  msg);
1089  GNUNET_assert (0 < s->msgs_in_queue);
1090  s->msgs_in_queue--;
1091  GNUNET_assert (msg->size <= s->bytes_in_queue);
1092  s->bytes_in_queue -= msg->size;
1093  if (NULL != msg->transmit_cont)
1094  msg->transmit_cont (msg->transmit_cont_cls,
1095  &s->address->peer,
1096  GNUNET_OK,
1097  msg->size,
1098  msg->size + s->overhead);
1099  s->overhead = 0;
1100  GNUNET_free (msg);
1101  }
1102  notify_session_monitor (plugin,
1103  s,
1105  GNUNET_asprintf (&stat_txt,
1106  "# bytes currently in %s_client buffers",
1107  plugin->protocol);
1109  stat_txt,
1110  - len,
1111  GNUNET_NO);
1112  GNUNET_free (stat_txt);
1113  GNUNET_asprintf (&stat_txt,
1114  "# bytes transmitted via %s_client",
1115  plugin->protocol);
1117  stat_txt,
1118  len,
1119  GNUNET_NO);
1120  GNUNET_free (stat_txt);
1121  return len;
1122 }
1123 
1124 
1130 static void
1131 client_wake_up (void *cls)
1132 {
1133  struct GNUNET_ATS_Session *s = cls;
1134 
1135  s->recv_wakeup_task = NULL;
1137  "Session %p/request %p: Waking up GET handle\n",
1138  s, s->get.easyhandle);
1139  if (H_PAUSED == s->put.state)
1140  {
1141  /* PUT request was paused, unpause */
1142  GNUNET_assert (s->put_disconnect_task != NULL);
1144  s->put_disconnect_task = NULL;
1145  s->put.state = H_CONNECTED;
1146  if (NULL != s->put.easyhandle)
1147  curl_easy_pause (s->put.easyhandle, CURLPAUSE_CONT);
1148  }
1149  if (NULL != s->get.easyhandle)
1150  curl_easy_pause (s->get.easyhandle, CURLPAUSE_CONT);
1151 }
1152 
1153 
1161 static int
1163  const struct GNUNET_MessageHeader *message)
1164 {
1165  struct GNUNET_ATS_Session *s = cls;
1166  struct HTTP_Client_Plugin *plugin;
1167  struct GNUNET_TIME_Relative delay;
1168  char *stat_txt;
1169 
1170  plugin = s->plugin;
1171  delay = s->plugin->env->receive (plugin->env->cls,
1172  s->address,
1173  s,
1174  message);
1175  GNUNET_asprintf (&stat_txt,
1176  "# bytes received via %s_client",
1177  plugin->protocol);
1179  stat_txt,
1180  ntohs (message->size),
1181  GNUNET_NO);
1182  GNUNET_free (stat_txt);
1183 
1185  if (GNUNET_TIME_absolute_get ().abs_value_us < s->next_receive.abs_value_us)
1186  {
1188  "Client: peer `%s' address `%s' next read delayed for %s\n",
1189  GNUNET_i2s (&s->address->peer),
1191  s->address->address,
1192  s->address->address_length),
1194  GNUNET_YES));
1195  }
1197  return GNUNET_OK;
1198 }
1199 
1200 
1211 static size_t
1212 client_receive_put (void *stream,
1213  size_t size,
1214  size_t nmemb,
1215  void *cls)
1216 {
1217  return size * nmemb;
1218 }
1219 
1220 
1231 static size_t
1232 client_receive (void *stream,
1233  size_t size,
1234  size_t nmemb,
1235  void *cls)
1236 {
1237  struct GNUNET_ATS_Session *s = cls;
1238  struct GNUNET_TIME_Absolute now;
1239  size_t len = size * nmemb;
1240 
1242  "Session %p / request %p: Received %u bytes from peer `%s'\n",
1243  s,
1244  s->get.easyhandle,
1245  len,
1246  GNUNET_i2s (&s->address->peer));
1247  now = GNUNET_TIME_absolute_get ();
1248  if (now.abs_value_us < s->next_receive.abs_value_us)
1249  {
1251  struct GNUNET_TIME_Relative delta
1253 
1255  "Session %p / request %p: No inbound bandwidth available! Next read was delayed for %s\n",
1256  s,
1257  s->get.easyhandle,
1259  GNUNET_YES));
1260  if (s->recv_wakeup_task != NULL)
1261  {
1263  s->recv_wakeup_task = NULL;
1264  }
1265  s->recv_wakeup_task
1267  &client_wake_up,
1268  s);
1269  return CURL_WRITEFUNC_PAUSE;
1270  }
1271  if (NULL == s->msg_tk)
1273  s);
1275  stream,
1276  len,
1277  GNUNET_NO,
1278  GNUNET_NO);
1279  return len;
1280 }
1281 
1282 
1288 static void
1289 client_run (void *cls)
1290 {
1291  struct HTTP_Client_Plugin *plugin = cls;
1292  int running;
1293  long http_statuscode;
1294  CURLMcode mret;
1295  CURLMsg *msg;
1296  int put_request; /* GNUNET_YES if easy handle is put, GNUNET_NO for get */
1297  int msgs_left;
1298 
1299  plugin->client_perform_task = NULL;
1300  /* While data are available or timeouts occured */
1301  do
1302  {
1303  running = 0;
1304  /* Perform operations for all handles */
1305  mret = curl_multi_perform (plugin->curl_multi_handle, &running);
1306 
1307  /* Get additional information for all handles */
1308  while (NULL != (msg = curl_multi_info_read (plugin->curl_multi_handle, &msgs_left)))
1309  {
1310  CURL *easy_h = msg->easy_handle;
1311  struct GNUNET_ATS_Session *s = NULL;
1312  char *d = NULL; /* curl requires 'd' to be a 'char *' */
1313 
1314  GNUNET_assert (NULL != easy_h);
1315 
1316  /* Obtain session from easy handle */
1317  GNUNET_assert (CURLE_OK == curl_easy_getinfo (easy_h, CURLINFO_PRIVATE, &d));
1318  s = (struct GNUNET_ATS_Session *) d;
1319  GNUNET_assert (NULL != s);
1320 
1321  if (msg->msg != CURLMSG_DONE)
1322  continue; /* This should not happen */
1323 
1324  /* Get HTTP response code */
1325  GNUNET_break (CURLE_OK == curl_easy_getinfo (easy_h,
1326  CURLINFO_RESPONSE_CODE, &http_statuscode));
1327 
1328  if (easy_h == s->put.easyhandle)
1329  put_request = GNUNET_YES;
1330  else
1331  put_request = GNUNET_NO;
1332 
1333  /* Log status of terminated request */
1334  if ((0 != msg->data.result) || (http_statuscode != 200))
1336  "Session %p/request %p: %s request to `%s' ended with status %i reason %i: `%s'\n",
1337  s, msg->easy_handle,
1338  (GNUNET_YES == put_request) ? "PUT" : "GET",
1339  GNUNET_i2s (&s->address->peer),
1340  http_statuscode,
1341  msg->data.result,
1342  curl_easy_strerror (msg->data.result));
1343  else
1345  "Session %p/request %p: %s request to `%s' ended normal\n",
1346  s, msg->easy_handle,
1347  (GNUNET_YES == put_request) ? "PUT" : "GET",
1348  GNUNET_i2s (&s->address->peer));
1349 
1350  /* Remove easy handle from multi handle */
1351  curl_multi_remove_handle (plugin->curl_multi_handle, easy_h);
1352 
1353  /* Clean up easy handle */
1354  curl_easy_cleanup (easy_h);
1355 
1356  /* Remove information */
1357  GNUNET_assert (plugin->cur_requests > 0);
1358  plugin->cur_requests--;
1360  "%s request to %s done, number of requests decreased to %u\n",
1361  (GNUNET_YES == put_request) ? "PUT" : "GET",
1362  s->url,
1363  plugin->cur_requests);
1364 
1365  if (GNUNET_YES == put_request)
1366  {
1367  /* Clean up a PUT request */
1368  s->put.easyhandle = NULL;
1369  s->put.s = NULL;
1370 
1371  switch (s->put.state) {
1372  case H_NOT_CONNECTED:
1373  case H_DISCONNECTED:
1374  case H_TMP_DISCONNECTED:
1375  /* This must not happen */
1376  GNUNET_break (0);
1377  break;
1379  /* Transport called send while disconnect in progess, reconnect */
1380  if (GNUNET_SYSERR == client_connect_put (s))
1381  {
1382  /* Reconnect failed, disconnect session */
1384  }
1385  break;
1386  case H_TMP_DISCONNECTING:
1387  /* PUT gets temporarily disconnected */
1389  break;
1390  case H_PAUSED:
1391  case H_CONNECTED:
1392  /* PUT gets permanently disconnected */
1393  s->put.state = H_DISCONNECTED;
1395  break;
1396  default:
1397  GNUNET_break (0);
1398  break;
1399  }
1400  }
1401  else if (GNUNET_NO == put_request)
1402  {
1403  /* Clean up a GET request */
1404  s->get.easyhandle = NULL;
1405  s->get.s = NULL;
1406 
1407  /* If we are emulating an XHR client we need to make another GET
1408  * request.
1409  */
1410  if (GNUNET_YES == plugin->emulate_xhr)
1411  {
1412  if (GNUNET_SYSERR == client_connect_get (s))
1414  }
1415  else
1416  {
1417  /* GET request was terminated, so disconnect session */
1419  }
1420  }
1421  else
1422  GNUNET_break (0); /* Must not happen */
1423 
1424  GNUNET_STATISTICS_set (plugin->env->stats,
1426  plugin->cur_requests,
1427  GNUNET_NO);
1428  }
1429  }
1430  while (mret == CURLM_CALL_MULTI_PERFORM);
1431  client_schedule (plugin, GNUNET_NO);
1432 }
1433 
1434 
1435 #ifdef TCP_STEALTH
1436 
1444 static curl_socket_t
1445 open_tcp_stealth_socket_cb (void *clientp,
1446  curlsocktype purpose,
1447  struct curl_sockaddr *address)
1448 {
1449  struct GNUNET_ATS_Session *s = clientp;
1450  int ret;
1451 
1452  switch (purpose)
1453  {
1454  case CURLSOCKTYPE_IPCXN:
1455  ret = socket (address->family,
1456  address->socktype,
1457  address->protocol);
1458  if (-1 == ret)
1459  return CURL_SOCKET_BAD;
1460  if ( ( (SOCK_STREAM != address->socktype) ||
1461  ( (0 != address->protocol) &&
1462  (IPPROTO_TCP != address->protocol))) )
1463  return (curl_socket_t) ret;
1464  if ( (0 != setsockopt (ret,
1465  IPPROTO_TCP,
1466  TCP_STEALTH,
1467  &s->address->peer,
1468  sizeof (struct GNUNET_PeerIdentity))) )
1469  {
1471  _("TCP_STEALTH not supported on this platform.\n"));
1472  (void) close (ret);
1473  return CURL_SOCKET_BAD;
1474  }
1475  return (curl_socket_t) ret;
1476  case CURLSOCKTYPE_ACCEPT:
1477  GNUNET_break (0);
1478  return CURL_SOCKET_BAD;
1479  break;
1480  case CURLSOCKTYPE_LAST:
1481  GNUNET_break (0);
1482  return CURL_SOCKET_BAD;
1483  default:
1484  GNUNET_break (0);
1485  return CURL_SOCKET_BAD;
1486  }
1487 }
1488 #endif
1489 
1490 
1497 static int
1499 {
1500  CURLMcode mret;
1501  struct HttpAddress *ha;
1502  uint32_t options;
1503 
1504  ha = (struct HttpAddress *) s->address->address;
1505  options = ntohl (ha->options);
1506  /* create get request */
1507  s->get.easyhandle = curl_easy_init ();
1508  s->get.s = s;
1509  if (0 != (options & HTTP_OPTIONS_TCP_STEALTH))
1510  {
1511 #ifdef TCP_STEALTH
1512  curl_easy_setopt (s->get.easyhandle,
1513  CURLOPT_OPENSOCKETFUNCTION,
1514  &open_tcp_stealth_socket_cb);
1515  curl_easy_setopt (s->get.easyhandle,
1516  CURLOPT_OPENSOCKETDATA,
1517  s);
1518 #else
1520  "Cannot connect, TCP STEALTH needed and not supported by kernel.\n");
1521  curl_easy_cleanup (s->get.easyhandle);
1522  s->get.easyhandle = NULL;
1523  s->get.s = NULL;
1524  return GNUNET_SYSERR;
1525 #endif
1526  }
1527 
1528 #if VERBOSE_CURL
1529  curl_easy_setopt (s->get.easyhandle,
1530  CURLOPT_VERBOSE,
1531  1L);
1532  curl_easy_setopt (s->get.easyhandle,
1533  CURLOPT_DEBUGFUNCTION,
1534  &client_log);
1535  curl_easy_setopt (s->get.easyhandle,
1536  CURLOPT_DEBUGDATA,
1537  &s->get);
1538 #endif
1539 #if BUILD_HTTPS
1540  curl_easy_setopt (s->get.easyhandle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
1541  {
1543  (options & HTTP_OPTIONS_VERIFY_CERTIFICATE))
1544  {
1545  curl_easy_setopt (s->get.easyhandle,
1546  CURLOPT_SSL_VERIFYPEER, 1L);
1547  curl_easy_setopt (s->get.easyhandle,
1548  CURLOPT_SSL_VERIFYHOST,
1549  2L);
1550  }
1551  else
1552  {
1553  curl_easy_setopt (s->get.easyhandle,
1554  CURLOPT_SSL_VERIFYPEER,
1555  0L);
1556  curl_easy_setopt (s->get.easyhandle,
1557  CURLOPT_SSL_VERIFYHOST,
1558  0L);
1559  }
1560  }
1561  curl_easy_setopt (s->get.easyhandle,
1562  CURLOPT_PROTOCOLS,
1563  CURLPROTO_HTTPS);
1564  curl_easy_setopt (s->get.easyhandle,
1565  CURLOPT_REDIR_PROTOCOLS,
1566  CURLPROTO_HTTPS);
1567 #else
1568  curl_easy_setopt (s->get.easyhandle,
1569  CURLOPT_PROTOCOLS,
1570  CURLPROTO_HTTP);
1571  curl_easy_setopt (s->get.easyhandle,
1572  CURLOPT_REDIR_PROTOCOLS,
1573  CURLPROTO_HTTP);
1574 #endif
1575 
1576  if (NULL != s->plugin->proxy_hostname)
1577  {
1578  curl_easy_setopt (s->get.easyhandle,
1579  CURLOPT_PROXY,
1580  s->plugin->proxy_hostname);
1581  curl_easy_setopt (s->get.easyhandle,
1582  CURLOPT_PROXYTYPE,
1583  s->plugin->proxytype);
1584  if (NULL != s->plugin->proxy_username)
1585  curl_easy_setopt (s->get.easyhandle,
1586  CURLOPT_PROXYUSERNAME,
1587  s->plugin->proxy_username);
1588  if (NULL != s->plugin->proxy_password)
1589  curl_easy_setopt (s->get.easyhandle,
1590  CURLOPT_PROXYPASSWORD,
1591  s->plugin->proxy_password);
1592  if (GNUNET_YES == s->plugin->proxy_use_httpproxytunnel)
1593  curl_easy_setopt (s->get.easyhandle,
1594  CURLOPT_HTTPPROXYTUNNEL,
1595  s->plugin->proxy_use_httpproxytunnel);
1596  }
1597 
1598  if (GNUNET_YES == s->plugin->emulate_xhr)
1599  {
1600  char *url;
1601 
1602  GNUNET_asprintf (&url,
1603  "%s,1",
1604  s->url);
1605  curl_easy_setopt (s->get.easyhandle,
1606  CURLOPT_URL,
1607  url);
1608  GNUNET_free(url);
1609  }
1610  else
1611  {
1612  curl_easy_setopt (s->get.easyhandle,
1613  CURLOPT_URL,
1614  s->url);
1615  }
1616  curl_easy_setopt (s->get.easyhandle,
1617  CURLOPT_READFUNCTION,
1618  &client_send_cb);
1619  curl_easy_setopt (s->get.easyhandle,
1620  CURLOPT_READDATA,
1621  s);
1622  curl_easy_setopt (s->get.easyhandle,
1623  CURLOPT_WRITEFUNCTION,
1624  &client_receive);
1625  curl_easy_setopt (s->get.easyhandle,
1626  CURLOPT_WRITEDATA,
1627  s);
1628  /* No timeout by default, timeout done with session timeout */
1629  curl_easy_setopt (s->get.easyhandle,
1630  CURLOPT_TIMEOUT,
1631  0L);
1632  curl_easy_setopt (s->get.easyhandle,
1633  CURLOPT_PRIVATE, s);
1634  curl_easy_setopt (s->get.easyhandle,
1635  CURLOPT_CONNECTTIMEOUT_MS,
1636  (long) (HTTP_CLIENT_NOT_VALIDATED_TIMEOUT.rel_value_us / 1000LL));
1637  curl_easy_setopt (s->get.easyhandle, CURLOPT_BUFFERSIZE,
1639 #if CURL_TCP_NODELAY
1640  curl_easy_setopt (ps->recv_endpoint,
1641  CURLOPT_TCP_NODELAY,
1642  1L);
1643 #endif
1644  curl_easy_setopt (s->get.easyhandle,
1645  CURLOPT_FOLLOWLOCATION,
1646  0L);
1647 
1648  mret = curl_multi_add_handle (s->plugin->curl_multi_handle,
1649  s->get.easyhandle);
1650  if (CURLM_OK != mret)
1651  {
1653  "Session %p : Failed to add GET handle to multihandle: `%s'\n",
1654  s,
1655  curl_multi_strerror (mret));
1656  curl_easy_cleanup (s->get.easyhandle);
1657  s->get.easyhandle = NULL;
1658  s->get.s = NULL;
1659  GNUNET_break (0);
1660  return GNUNET_SYSERR;
1661  }
1662  s->plugin->cur_requests++;
1664  "GET request `%s' established, number of requests increased to %u\n",
1665  s->url,
1666  s->plugin->cur_requests);
1667  return GNUNET_OK;
1668 }
1669 
1670 
1677 static int
1679 {
1680  CURLMcode mret;
1681  struct HttpAddress *ha;
1682  uint32_t options;
1683 
1684  ha = (struct HttpAddress *) s->address->address;
1685  options = ntohl (ha->options);
1686  /* create put request */
1688  "Session %p: Init PUT handle\n",
1689  s);
1690  s->put.easyhandle = curl_easy_init ();
1691  s->put.s = s;
1692 #if VERBOSE_CURL
1693  curl_easy_setopt (s->put.easyhandle,
1694  CURLOPT_VERBOSE,
1695  1L);
1696  curl_easy_setopt (s->put.easyhandle,
1697  CURLOPT_DEBUGFUNCTION,
1698  &client_log);
1699  curl_easy_setopt (s->put.easyhandle,
1700  CURLOPT_DEBUGDATA,
1701  &s->put);
1702 #endif
1703  if (0 != (options & HTTP_OPTIONS_TCP_STEALTH))
1704  {
1705 #ifdef TCP_STEALTH
1706  curl_easy_setopt (s->put.easyhandle,
1707  CURLOPT_OPENSOCKETFUNCTION,
1708  &open_tcp_stealth_socket_cb);
1709  curl_easy_setopt (s->put.easyhandle,
1710  CURLOPT_OPENSOCKETDATA,
1711  s);
1712 #else
1714  "Cannot connect, TCP STEALTH needed and not supported by kernel.\n");
1715  curl_easy_cleanup (s->put.easyhandle);
1716  s->put.easyhandle = NULL;
1717  s->put.s = NULL;
1718  s->put.state = H_DISCONNECTED;
1719  return GNUNET_SYSERR;
1720 #endif
1721  }
1722 #if BUILD_HTTPS
1723  curl_easy_setopt (s->put.easyhandle,
1724  CURLOPT_SSLVERSION,
1725  CURL_SSLVERSION_TLSv1);
1726  {
1727  struct HttpAddress *ha;
1728  ha = (struct HttpAddress *) s->address->address;
1729 
1731  (ntohl (ha->options) & HTTP_OPTIONS_VERIFY_CERTIFICATE))
1732  {
1733  curl_easy_setopt (s->put.easyhandle,
1734  CURLOPT_SSL_VERIFYPEER,
1735  1L);
1736  curl_easy_setopt (s->put.easyhandle,
1737  CURLOPT_SSL_VERIFYHOST,
1738  2L);
1739  }
1740  else
1741  {
1742  curl_easy_setopt (s->put.easyhandle,
1743  CURLOPT_SSL_VERIFYPEER,
1744  0L);
1745  curl_easy_setopt (s->put.easyhandle,
1746  CURLOPT_SSL_VERIFYHOST,
1747  0L);
1748  }
1749  }
1750  curl_easy_setopt (s->put.easyhandle,
1751  CURLOPT_PROTOCOLS,
1752  CURLPROTO_HTTPS);
1753  curl_easy_setopt (s->put.easyhandle,
1754  CURLOPT_REDIR_PROTOCOLS,
1755  CURLPROTO_HTTPS);
1756 #else
1757  curl_easy_setopt (s->put.easyhandle,
1758  CURLOPT_PROTOCOLS,
1759  CURLPROTO_HTTP);
1760  curl_easy_setopt (s->put.easyhandle,
1761  CURLOPT_REDIR_PROTOCOLS,
1762  CURLPROTO_HTTP);
1763 #endif
1764  if (NULL != s->plugin->proxy_hostname)
1765  {
1766  curl_easy_setopt (s->put.easyhandle,
1767  CURLOPT_PROXY,
1768  s->plugin->proxy_hostname);
1769  curl_easy_setopt (s->put.easyhandle,
1770  CURLOPT_PROXYTYPE,
1771  s->plugin->proxytype);
1772  if (NULL != s->plugin->proxy_username)
1773  curl_easy_setopt (s->put.easyhandle,
1774  CURLOPT_PROXYUSERNAME,
1775  s->plugin->proxy_username);
1776  if (NULL != s->plugin->proxy_password)
1777  curl_easy_setopt (s->put.easyhandle,
1778  CURLOPT_PROXYPASSWORD,
1779  s->plugin->proxy_password);
1780  if (GNUNET_YES == s->plugin->proxy_use_httpproxytunnel)
1781  curl_easy_setopt (s->put.easyhandle,
1782  CURLOPT_HTTPPROXYTUNNEL,
1783  s->plugin->proxy_use_httpproxytunnel);
1784  }
1785 
1786  curl_easy_setopt (s->put.easyhandle,
1787  CURLOPT_URL,
1788  s->url);
1789  curl_easy_setopt (s->put.easyhandle,
1790  CURLOPT_UPLOAD,
1791  1L);
1792  curl_easy_setopt (s->put.easyhandle,
1793  CURLOPT_READFUNCTION,
1794  &client_send_cb);
1795  curl_easy_setopt (s->put.easyhandle,
1796  CURLOPT_READDATA,
1797  s);
1798  curl_easy_setopt (s->put.easyhandle,
1799  CURLOPT_WRITEFUNCTION,
1801  curl_easy_setopt (s->put.easyhandle,
1802  CURLOPT_WRITEDATA,
1803  s);
1804  /* No timeout by default, timeout done with session timeout */
1805  curl_easy_setopt (s->put.easyhandle,
1806  CURLOPT_TIMEOUT,
1807  0L);
1808  curl_easy_setopt (s->put.easyhandle,
1809  CURLOPT_PRIVATE,
1810  s);
1811  curl_easy_setopt (s->put.easyhandle,
1812  CURLOPT_CONNECTTIMEOUT_MS,
1813  (long) (HTTP_CLIENT_NOT_VALIDATED_TIMEOUT.rel_value_us / 1000LL));
1814  curl_easy_setopt (s->put.easyhandle, CURLOPT_BUFFERSIZE,
1816 #if CURL_TCP_NODELAY
1817  curl_easy_setopt (s->put.easyhandle, CURLOPT_TCP_NODELAY, 1);
1818 #endif
1819  mret = curl_multi_add_handle (s->plugin->curl_multi_handle,
1820  s->put.easyhandle);
1821  if (CURLM_OK != mret)
1822  {
1824  "Session %p : Failed to add PUT handle to multihandle: `%s'\n",
1825  s, curl_multi_strerror (mret));
1826  curl_easy_cleanup (s->put.easyhandle);
1827  s->put.easyhandle = NULL;
1828  s->put.s = NULL;
1829  s->put.state = H_DISCONNECTED;
1830  return GNUNET_SYSERR;
1831  }
1832  s->put.state = H_CONNECTED;
1833  s->plugin->cur_requests++;
1834 
1836  "PUT request `%s' established, number of requests increased to %u\n",
1837  s->url, s->plugin->cur_requests);
1838 
1839  return GNUNET_OK;
1840 }
1841 
1842 
1849 static int
1851 {
1852  struct HTTP_Client_Plugin *plugin = s->plugin;
1853  int res = GNUNET_OK;
1854 
1855  /* create url */
1856  if (NULL ==
1858  s->address->address,
1859  s->address->address_length))
1860  {
1862  "Invalid address peer `%s'\n",
1863  GNUNET_i2s(&s->address->peer));
1864  return GNUNET_SYSERR;
1865  }
1866 
1867  GNUNET_asprintf (&s->url,
1868  "%s/%s;%u",
1870  s->address->address,
1871  s->address->address_length),
1872  GNUNET_i2s_full (plugin->env->my_identity),
1873  plugin->last_tag);
1874 
1875  plugin->last_tag++;
1877  "Initiating outbound session peer `%s' using address `%s'\n",
1878  GNUNET_i2s (&s->address->peer), s->url);
1879 
1880  if (GNUNET_SYSERR == client_connect_get (s))
1881  return GNUNET_SYSERR;
1882  /* If we are emulating an XHR client then delay sending a PUT request until
1883  * there is something to send.
1884  */
1885  if (GNUNET_YES == plugin->emulate_xhr)
1886  {
1888  }
1889  else if (GNUNET_SYSERR == client_connect_put (s))
1890  return GNUNET_SYSERR;
1891 
1893  "Session %p: connected with GET %p and PUT %p\n",
1894  s, s->get.easyhandle,
1895  s->put.easyhandle);
1896  /* Perform connect */
1897  GNUNET_STATISTICS_set (plugin->env->stats,
1899  plugin->cur_requests,
1900  GNUNET_NO);
1901  /* Re-schedule since handles have changed */
1902  if (NULL != plugin->client_perform_task)
1903  {
1905  plugin->client_perform_task = NULL;
1906  }
1907 
1908  /* Schedule task to run immediately */
1910  plugin);
1911  return res;
1912 }
1913 
1914 
1922 static enum GNUNET_NetworkType
1924  struct GNUNET_ATS_Session *session)
1925 {
1926  return session->scope;
1927 }
1928 
1929 
1937 static enum GNUNET_NetworkType
1939  const struct GNUNET_HELLO_Address *address)
1940 {
1941  struct HTTP_Client_Plugin *plugin = cls;
1942 
1943  return http_common_get_network_for_address (plugin->env,
1944  address);
1945 }
1946 
1947 
1953 static void
1955 {
1956  struct GNUNET_ATS_Session *s = cls;
1957  struct GNUNET_TIME_Relative left;
1958 
1959  s->timeout_task = NULL;
1961  if (0 != left.rel_value_us)
1962  {
1963  /* not actually our turn yet, but let's at least update
1964  the monitor, it may think we're about to die ... */
1966  s,
1970  s);
1971  return;
1972  }
1973  LOG (TIMEOUT_LOG,
1974  "Session %p was idle for %s, disconnecting\n",
1975  s,
1977  GNUNET_YES));
1980  s));
1981 }
1982 
1983 
1992 static struct GNUNET_ATS_Session *
1994  const struct GNUNET_HELLO_Address *address)
1995 {
1996  struct HTTP_Client_Plugin *plugin = cls;
1997  struct GNUNET_ATS_Session *s;
1998  struct sockaddr *sa;
1999  enum GNUNET_NetworkType net_type;
2000  size_t salen = 0;
2001  int res;
2002 
2003  GNUNET_assert (NULL != address->address);
2004 
2005  /* find existing session */
2006  s = client_lookup_session (plugin, address);
2007  if (NULL != s)
2008  return s;
2009 
2010  /* create a new session */
2011  if (plugin->max_requests <= plugin->cur_requests)
2012  {
2014  "Maximum number of requests (%u) reached: "
2015  "cannot connect to peer `%s'\n",
2016  plugin->max_requests,
2017  GNUNET_i2s (&address->peer));
2018  return NULL;
2019  }
2020 
2021  /* Determine network location */
2022  net_type = GNUNET_NT_UNSPECIFIED;
2024  address->address_length,
2025  &res);
2026  if (GNUNET_SYSERR == res)
2027  return NULL;
2028  if (GNUNET_YES == res)
2029  {
2030  GNUNET_assert (NULL != sa);
2031  if (AF_INET == sa->sa_family)
2032  {
2033  salen = sizeof (struct sockaddr_in);
2034  }
2035  else if (AF_INET6 == sa->sa_family)
2036  {
2037  salen = sizeof (struct sockaddr_in6);
2038  }
2039  net_type = plugin->env->get_address_type (plugin->env->cls, sa, salen);
2040  GNUNET_free (sa);
2041  }
2042  else if (GNUNET_NO == res)
2043  {
2044  /* Cannot convert to sockaddr -> is external hostname */
2045  net_type = GNUNET_NT_WAN;
2046  }
2047  if (GNUNET_NT_UNSPECIFIED == net_type)
2048  {
2049  GNUNET_break (0);
2050  return NULL;
2051  }
2052 
2053  s = GNUNET_new (struct GNUNET_ATS_Session);
2054  s->plugin = plugin;
2055  s->address = GNUNET_HELLO_address_copy (address);
2056  s->scope = net_type;
2057 
2058  s->put.state = H_NOT_CONNECTED;
2062  s);
2064  "Created new session %p for `%s' address `%s''\n",
2065  s,
2067  s->address->address,
2068  s->address->address_length),
2069  GNUNET_i2s (&s->address->peer));
2070 
2071  /* add new session */
2073  &s->address->peer,
2074  s,
2076  /* initiate new connection */
2077  if (GNUNET_SYSERR == client_connect (s))
2078  {
2080  "Cannot connect to peer `%s' address `%s''\n",
2083  GNUNET_i2s (&s->address->peer));
2085  return NULL;
2086  }
2087  notify_session_monitor (plugin,
2088  s,
2090  notify_session_monitor (plugin,
2091  s,
2092  GNUNET_TRANSPORT_SS_UP); /* or handshake? */
2093  return s;
2094 }
2095 
2096 
2103 static int
2105 {
2106  curl_global_init (CURL_GLOBAL_ALL);
2107  plugin->curl_multi_handle = curl_multi_init ();
2108 
2109  if (NULL == plugin->curl_multi_handle)
2110  {
2112  _("Could not initialize curl multi handle, failed to start %s plugin!\n"),
2113  plugin->name);
2114  return GNUNET_SYSERR;
2115  }
2116  return GNUNET_OK;
2117 }
2118 
2119 
2132 static int
2134  const void *addr,
2135  size_t addrlen)
2136 {
2137  /* A HTTP/S client does not have any valid address so:*/
2138  return GNUNET_NO;
2139 }
2140 
2141 
2148 void *
2150 {
2151  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2152  struct HTTP_Client_Plugin *plugin = api->cls;
2153 
2154  if (NULL == api->cls)
2155  {
2156  /* Stub shutdown */
2157  GNUNET_free (api);
2158  return NULL;
2159  }
2161  _("Shutting down plugin `%s'\n"),
2162  plugin->name);
2165  plugin);
2166  if (NULL != plugin->client_perform_task)
2167  {
2169  plugin->client_perform_task = NULL;
2170  }
2171  if (NULL != plugin->curl_multi_handle)
2172  {
2173  curl_multi_cleanup (plugin->curl_multi_handle);
2174  plugin->curl_multi_handle = NULL;
2175  }
2176  curl_global_cleanup ();
2178  _("Shutdown for plugin `%s' complete\n"),
2179  plugin->name);
2184  GNUNET_free (plugin);
2185  GNUNET_free (api);
2186  return NULL;
2187 }
2188 
2189 
2196 static int
2198 {
2199  unsigned long long max_requests;
2200  char *proxy_type;
2201 
2202  /* Optional parameters */
2203  if (GNUNET_OK !=
2205  plugin->name,
2206  "MAX_CONNECTIONS",
2207  &max_requests))
2208  max_requests = 128;
2209  plugin->max_requests = max_requests;
2210 
2212  _("Maximum number of requests is %u\n"),
2213  plugin->max_requests);
2214 
2215  /* Read proxy configuration */
2216  if (GNUNET_OK ==
2218  plugin->name,
2219  "PROXY",
2220  &plugin->proxy_hostname))
2221  {
2223  "Found proxy host: `%s'\n",
2224  plugin->proxy_hostname);
2225  /* proxy username */
2226  if (GNUNET_OK ==
2228  plugin->name,
2229  "PROXY_USERNAME",
2230  &plugin->proxy_username))
2231  {
2233  "Found proxy username name: `%s'\n",
2234  plugin->proxy_username);
2235  }
2236 
2237  /* proxy password */
2238  if (GNUNET_OK ==
2240  plugin->name,
2241  "PROXY_PASSWORD",
2242  &plugin->proxy_password))
2243  {
2245  "Found proxy password name: `%s'\n",
2246  plugin->proxy_password);
2247  }
2248 
2249  /* proxy type */
2250  if (GNUNET_OK ==
2252  plugin->name,
2253  "PROXY_TYPE",
2254  &proxy_type))
2255  {
2256  GNUNET_STRINGS_utf8_toupper (proxy_type, proxy_type);
2257 
2258  if (0 == strcmp(proxy_type, "HTTP"))
2259  plugin->proxytype = CURLPROXY_HTTP;
2260  else if (0 == strcmp(proxy_type, "SOCKS4"))
2261  plugin->proxytype = CURLPROXY_SOCKS4;
2262  else if (0 == strcmp(proxy_type, "SOCKS5"))
2263  plugin->proxytype = CURLPROXY_SOCKS5;
2264  else if (0 == strcmp(proxy_type, "SOCKS4A"))
2265  plugin->proxytype = CURLPROXY_SOCKS4A;
2266  else if (0 == strcmp(proxy_type, "SOCKS5_HOSTNAME "))
2267  plugin->proxytype = CURLPROXY_SOCKS5_HOSTNAME ;
2268  else
2269  {
2271  _("Invalid proxy type: `%s', disabling proxy! Check configuration!\n"),
2272  proxy_type);
2273 
2274  GNUNET_free (proxy_type);
2275  GNUNET_free (plugin->proxy_hostname);
2276  plugin->proxy_hostname = NULL;
2278  plugin->proxy_username = NULL;
2280  plugin->proxy_password = NULL;
2281 
2282  return GNUNET_SYSERR;
2283  }
2284 
2286  "Found proxy type: `%s'\n",
2287  proxy_type);
2288  }
2289 
2290  /* proxy http tunneling */
2293  plugin->name,
2294  "PROXY_HTTP_TUNNELING");
2297 
2298  GNUNET_free_non_null (proxy_type);
2299  }
2300 
2301  /* Should we emulate an XHR client for testing? */
2302  plugin->emulate_xhr
2304  plugin->name,
2305  "EMULATE_XHR");
2306  return GNUNET_OK;
2307 }
2308 
2309 
2318 static const char *
2320  const void *addr,
2321  size_t addrlen)
2322 {
2324  addr,
2325  addrlen);
2326 }
2327 
2328 
2338 static void
2340  const struct GNUNET_PeerIdentity *peer,
2341  struct GNUNET_ATS_Session *session)
2342 {
2344 }
2345 
2346 
2357 static void
2359  const struct GNUNET_PeerIdentity *peer,
2360  struct GNUNET_ATS_Session *s,
2361  struct GNUNET_TIME_Relative delay)
2362 {
2365  "New inbound delay %s\n",
2367  GNUNET_NO));
2368  if (s->recv_wakeup_task != NULL)
2369  {
2371  s->recv_wakeup_task
2373  &client_wake_up,
2374  s);
2375  }
2376 }
2377 
2378 
2388 static int
2390  const struct GNUNET_PeerIdentity *peer,
2391  void *value)
2392 {
2393  struct HTTP_Client_Plugin *plugin = cls;
2394  struct GNUNET_ATS_Session *session = value;
2395 
2396  notify_session_monitor (plugin,
2397  session,
2399  notify_session_monitor (plugin,
2400  session,
2401  GNUNET_TRANSPORT_SS_UP); /* FIXME: or handshake? */
2402  return GNUNET_OK;
2403 }
2404 
2405 
2418 static void
2421  void *sic_cls)
2422 {
2423  struct HTTP_Client_Plugin *plugin = cls;
2424 
2425  plugin->sic = sic;
2426  plugin->sic_cls = sic_cls;
2427  if (NULL != sic)
2428  {
2431  plugin);
2432  /* signal end of first iteration */
2433  sic (sic_cls, NULL, NULL);
2434  }
2435 }
2436 
2437 
2441 void *
2443 {
2446  struct HTTP_Client_Plugin *plugin;
2447 
2448  if (NULL == env->receive)
2449  {
2450  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
2451  initialze the plugin or the API */
2453  api->cls = NULL;
2457  return api;
2458  }
2459 
2460  plugin = GNUNET_new (struct HTTP_Client_Plugin);
2461  plugin->env = env;
2463  GNUNET_YES);
2465  api->cls = plugin;
2466  api->send = &http_client_plugin_send;
2480 #if BUILD_HTTPS
2481  plugin->name = "transport-https_client";
2482  plugin->protocol = "https";
2483 #else
2484  plugin->name = "transport-http_client";
2485  plugin->protocol = "http";
2486 #endif
2487  plugin->last_tag = 1;
2488 
2489  if (GNUNET_SYSERR == client_configure_plugin (plugin))
2490  {
2492  return NULL;
2493  }
2494 
2495  /* Start client */
2496  if (GNUNET_SYSERR == client_start (plugin))
2497  {
2499  return NULL;
2500  }
2501  return api;
2502 }
2503 
2504 /* end of plugin_transport_http_client.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static enum GNUNET_NetworkType http_client_plugin_get_network_for_address(void *cls, const struct GNUNET_HELLO_Address *address)
Function obtain the network type for an address.
size_t address_length
Number of bytes in address.
static int http_client_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
Another peer has suggested an address for this peer and transport plugin.
Session is being torn down and about to disappear.
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
uint32_t num_bytes_pending
Number of bytes pending transmission for this session.
HTTP_PUT_REQUEST_STATE
State of a HTTP PUT request.
static int client_receive_mst_cb(void *cls, const struct GNUNET_MessageHeader *message)
Callback for message stream tokenizer.
#define HTTP_CLIENT_SESSION_TIMEOUT
static unsigned int http_client_query_keepalive_factor(void *cls)
Function that is called to get the keepalive factor.
struct GNUNET_MessageStreamTokenizer * msg_tk
Message stream tokenizer for incoming data.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
static int http_client_plugin_session_disconnect(void *cls, struct GNUNET_ATS_Session *s)
Disconnect a session.
uint32_t options
Address options see enum HttpAddressOptions
GNUNET_TRANSPORT_AddressToString address_to_string
Function that will be called to convert a binary address to a string (numeric conversion only)...
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
struct GNUNET_SCHEDULER_Task * recv_wakeup_task
Task to wake up client receive handle when receiving is allowed again.
uint64_t rel_value_us
The actual value.
static int client_configure_plugin(struct HTTP_Client_Plugin *plugin)
Configure plugin.
const void * address
Binary representation of the address (plugin-specific).
char * buf
buffer containing data to send
unsigned int msgs_in_queue
Number of messages waiting for transmission to this peer.
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_SCHEDULER_Task * timeout_task
Session timeout task.
struct HTTP_Message * msg_tail
previous pointer for double linked list
curl_proxytype proxytype
Type of proxy server:
uint32_t last_tag
Last used unique HTTP connection tag.
library to make it easy to download JSON replies over HTTP
struct Plugin * plugin
Pointer to the global plugin struct.
const char * http_common_plugin_address_to_url(void *cls, const void *addr, size_t addrlen)
FIXME.
int http_common_plugin_string_to_address(void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added)
Function called to convert a string address to a binary address.
struct HTTP_Client_Plugin * plugin
Pointer to the global plugin struct.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
GNUNET_TRANSPORT_DisconnectPeerFunction disconnect_peer
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
#define PUT_DISCONNECT_TIMEOUT
GNUNET_TRANSPORT_AddressToType get_address_type
Function that will be called to figure if an address is an loopback, LAN, WAN etc.
int is_inbound
GNUNET_YES if this is an inbound connection, GNUNET_NO if this is an outbound connection, GNUNET_SYSERR if connections of this plugin are so fundamentally bidirectional that they have no &#39;initiator&#39;
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:245
char * proxy_username
Username for the proxy server.
enum GNUNET_TRANSPORT_SessionState state
New state of the session.
size_t pos
amount of data already sent
static int client_connect_get(struct GNUNET_ATS_Session *s)
Connect GET request.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
char * protocol
Plugin protocol http, https.
static int send_session_info_iter(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Return information about the given session to the monitor callback.
#define GNUNET_TIME_UNIT_SECONDS
One second.
GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
struct RequestHandle put
Handle for the HTTP PUT request.
Message to send using http.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
struct GNUNET_SERVER_MessageStreamTokenizer * msg_tk
Message stream tokenizer for incoming data.
GNUNET_TRANSPORT_SessionMonitorSetup setup_monitor
Function to monitor the sessions managed by the plugin.
struct HTTP_Message * next
next pointer for double linked list
static size_t client_receive_put(void *stream, size_t size, size_t nmemb, void *cls)
Callback method used with libcurl when data for a PUT request are received.
static curl_proxytype proxy_type
Proxy type we are using (can be NULL).
const struct GNUNET_PeerIdentity * my_identity
Identity of this peer.
static void client_session_timeout(void *cls)
Session was idle, so disconnect it.
struct GNUNET_TIME_Absolute timeout
When does this session time out.
static void http_client_plugin_update_session_timeout(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Session *session)
Function that will be called whenever the transport service wants to notify the plugin that a session...
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
Wide area network (i.e.
Definition: gnunet_nt_lib.h:55
static struct GNUNET_ATS_Session * http_client_plugin_get_session(void *cls, const struct GNUNET_HELLO_Address *address)
Creates a new outbound session the transport service will use to send data to the peer...
#define GNUNET_NO
Definition: gnunet_common.h:81
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void client_run(void *cls)
Task performing curl operations.
struct GNUNET_HELLO_Address * address
Address.
static void client_wake_up(void *cls)
Wake up a curl handle which was suspended.
struct GNUNET_TRANSPORT_PluginEnvironment * env
Our environment.
struct RequestHandle get
Handle for the HTTP GET request.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
struct HTTP_Message * msg_head
next pointer for double linked list
struct GNUNET_SCHEDULER_Task * put_disconnect_task
Session timeout task.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
const struct GNUNET_HELLO_Address * address
Address used by the session.
unsigned long long bytes_in_queue
Number of bytes waiting for transmission to this peer.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
static int ret
Final status code.
Definition: gnunet-arm.c:89
uint64_t abs_value_us
The actual value.
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:35
uint32_t num_msg_pending
Number of messages pending transmission for this session.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
void * transmit_cont_cls
Closure for transmit_cont.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
void GNUNET_NETWORK_fdset_copy_native(struct GNUNET_NETWORK_FDSet *to, const fd_set *from, int nfds)
Copy a native fd set into the GNUnet representation.
Definition: network.c:1308
struct GNUNET_TIME_Absolute receive_delay
Until when does this plugin refuse to receive to manage staying within the inbound quota...
The request handle.
GNUNET_TRANSPORT_TransmitContinuation transmit_cont
Continuation function to call once the transmission buffer has again space available.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
int proxy_use_httpproxytunnel
Use proxy tunneling: Tunnel all operations through a given HTTP instead of have the proxy evaluate th...
GNUNET_TRANSPORT_SessionEnd session_end
Function that must be called by the plugin when a non-NULL session handle stops being valid (is destr...
Paused, nothing to send.
GNUNET_TRANSPORT_PluginReceiveCallback receive
Function that should be called by the transport plugin whenever a message is received.
struct GNUNET_TIME_Absolute next_receive
Absolute time when to receive data again Used for receive throttling.
GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout
Function that will be called whenever the transport service wants to notify the plugin that a session...
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1554
static struct GNUNET_ATS_SolverFunctions * plugin
Our solver.
const struct GNUNET_HELLO_Address * address
Address we are looking for.
Information about a plugin&#39;s session.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:130
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1538
static void notify_session_monitor(struct HTTP_Client_Plugin *plugin, struct GNUNET_ATS_Session *session, enum GNUNET_TRANSPORT_SessionState state)
If a session monitor is attached, notify it about the new session state.
void GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
Convert the utf-8 input string to upper case.
Definition: strings.c:580
void * cls
Closure for the various callbacks.
enum State state
current state of profiling
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
void * cls
Closure for all of the callbacks.
static void client_put_disconnect(void *cls)
When we have nothing to transmit, we pause the HTTP PUT after a while (so that gnurl stops asking)...
Temporarily disconnected.
#define GNUNET_memcpy(dst, src, n)
#define LIBGNUNET_PLUGIN_TRANSPORT_INIT
static char * value
Value of the record to add/remove.
static int client_schedule(struct HTTP_Client_Plugin *plugin, int now)
Function setting up file descriptors and scheduling task to run.
GNUNET_TRANSPORT_StringToAddress string_to_address
Function that will be called to convert a string address to binary (numeric conversion only)...
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:413
static struct GNUNET_ATS_Session * client_lookup_session(struct HTTP_Client_Plugin *plugin, const struct GNUNET_HELLO_Address *address)
Check if a sessions exists for an specific address.
Information about ongoing sessions of the transport client.
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1273
The transport service will pass a pointer to a struct of this type as the first and only argument to ...
static enum GNUNET_NetworkType scope
Which network scope do we belong to?
GNUNET_TRANSPORT_GetNetworkType get_network
Function to obtain the network type for a session.
Handle to a message stream tokenizer.
Definition: mst.c:43
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:83
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:727
collection of IO descriptors
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1829
void http_common_plugin_address_pretty_printer(void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
Convert the transports address to a nice, human-readable format.
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:87
uint32_t options
My options to be included in the address.
void(* GNUNET_TRANSPORT_SessionInfoCallback)(void *cls, struct GNUNET_ATS_Session *session, const struct GNUNET_TRANSPORT_SessionInfo *info)
Function called by the plugin with information about the current sessions managed by the plugin (for ...
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:439
int GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:116
struct GNUNET_TIME_Absolute session_timeout
At what time will this session timeout (unless activity happens)?
static int session_lookup_client_by_address(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Locate the seession object for a given address.
static ssize_t http_client_plugin_send(void *cls, struct GNUNET_ATS_Session *s, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
Function that can be used by the transport service to transmit a message using the plugin...
Internal representation of the hash map.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
GNUNET_TRANSPORT_UpdateInboundDelay update_inbound_delay
Function that will be called whenever the transport service wants to notify the plugin that the inbou...
Closure for session_lookup_client_by_address().
static int client_connect_put(struct GNUNET_ATS_Session *s)
Connect a HTTP put request.
int state
The processing state.
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
static int destroy_session_cb(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Callback to destroys all sessions on exit.
static int res
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static enum GNUNET_NetworkType http_client_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
Function obtain the network type for a session.
static void client_reschedule_session_timeout(struct GNUNET_ATS_Session *s)
Increment session timeout due to activity for session s.
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
static CURL * curl
Current CURL handle.
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.
static int client_connect(struct GNUNET_ATS_Session *s)
Connect both PUT and GET request for a session.
size_t size
buffer length
struct GNUNET_CONTAINER_MultiPeerMap * sessions
Open sessions.
static const char * http_client_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
Function to convert an address to a human-readable string.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
char * url
The URL to connect to.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
#define HTTP_CLIENT_NOT_VALIDATED_TIMEOUT
static size_t client_receive(void *stream, size_t size, size_t nmemb, void *cls)
Callback method used with libcurl when data for a GET request are received.
int emulate_xhr
Should we emulate an XHR client for testing?
enum GNUNET_NetworkType scope
ATS network type.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
void(* GNUNET_TRANSPORT_TransmitContinuation)(void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire)
Function called by the GNUNET_TRANSPORT_TransmitFunction upon "completion".
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static struct GNUNET_SCHEDULER_Task * timeout_task
Task to be run on timeout.
Definition: gnunet-arm.c:119
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
struct GNUNET_PeerIdentity peer
For which peer is this an address?
Just created, not yet connected.
static void http_client_plugin_peer_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
Enable TCP Stealth-style port knocking.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
void * sic_cls
Closure for sic.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
#define LIBGNUNET_PLUGIN_TRANSPORT_DONE
Encapsulation of all of the state of the plugin.
Allow multiple values with the same key.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don&#39;t receive messages from the peer...
const char * http_common_plugin_address_to_string(const char *plugin, const void *addr, size_t addrlen)
Function called for a quick conversion of the binary address to a numeric address.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
This is just an update about the session, the state did not change.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_NetworkType http_common_get_network_for_address(struct GNUNET_TRANSPORT_PluginEnvironment *env, const struct GNUNET_HELLO_Address *address)
Function obtain the network type for an address.
GNUNET_TRANSPORT_QueryKeepaliveFactorFunction query_keepalive_factor
Function that is used to query keepalive factor.
The identity of the host (wraps the signing key of the peer).
static void http_client_plugin_setup_monitor(void *cls, GNUNET_TRANSPORT_SessionInfoCallback sic, void *sic_cls)
Begin monitoring sessions of a plugin.
struct sockaddr * http_common_socket_from_address(const void *addr, size_t addrlen, int *res)
Create a socketaddr from a HTTP address.
struct GNUNET_SCHEDULER_Task * client_perform_task
curl perform task
unsigned int cur_requests
Current number of sockets the plugin can use Each http connections are two requests.
#define HTTP_STAT_STR_CONNECTIONS
struct GNUNET_PeerIdentity target
To whom are we talking to.
CURLM * curl_multi_handle
cURL Multihandle
#define PLUGIN_NAME
An address for communicating with a peer.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:109
struct GNUNET_STATISTICS_Handle * stats
Handle for reporting statistics.
struct GNUNET_ATS_Session * ret
Session that was found.
#define GNUNET_log(kind,...)
The session was created (first call for each session object).
Entry in list of pending tasks.
Definition: scheduler.c:134
static int client_start(struct HTTP_Client_Plugin *plugin)
Setup http_client plugin.
struct HTTP_Message * prev
previous pointer for double linked list
unsigned int max_requests
Maximum number of sockets the plugin can use Each http connections are two requests.
size_t overhead
Outbound overhead due to HTTP connection Add to next message of this session when calling callback...
Verify X509 server certificate, it should be valid.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
GNUNET_TRANSPORT_AddressPrettyPrinter address_pretty_printer
Function to pretty-print addresses.
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
char * proxy_hostname
Proxy configuration: hostname or ip of the proxy server.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition: time.c:353
#define LOG(kind,...)
Temporary disconnect in progress due to inactivity.
struct GNUNET_ATS_Session * s
The related session.
Run with the default priority (normal P2P operations).
GNUNET_TRANSPORT_CheckAddress check_address
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
GNUNET_TRANSPORT_SessionState
Possible states of a session in a plugin.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
uint32_t data
The data value.
static void http_client_plugin_update_inbound_delay(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Session *s, struct GNUNET_TIME_Relative delay)
Function that will be called whenever the transport service wants to notify the plugin that the inbou...
static char * address
GNS address for this phone.
CURL * easyhandle
The curl easy handle.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_HELLO_address_free(addr)
Free an address.
HTTP addresses including a full URI.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
#define TIMEOUT_LOG
#define GNUNET_malloc(size)
Wrapper around malloc.
char * proxy_password
Password for the proxy server.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
Send request while temporary disconnect, reconnect.
GNUNET_TRANSPORT_GetNetworkTypeForAddress get_network_for_address
Function to obtain the network type for an address.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
Category of last resort.
Definition: gnunet_nt_lib.h:40
static size_t client_send_cb(void *stream, size_t size, size_t nmemb, void *cls)
Callback method used with libcurl Method is called when libcurl needs to read data during sending...
static void client_delete_session(struct GNUNET_ATS_Session *s)
Delete session s.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965