GNUnet  0.11.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 \
32  libgnunet_plugin_transport_https_client_init
33 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE \
34  libgnunet_plugin_transport_https_client_done
35 #else
36 #define PLUGIN_NAME "http_client"
37 #define HTTP_STAT_STR_CONNECTIONS "# HTTP client connections"
38 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT \
39  libgnunet_plugin_transport_http_client_init
40 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE \
41  libgnunet_plugin_transport_http_client_done
42 #endif
43 
44 #define VERBOSE_CURL GNUNET_NO
45 
46 #define PUT_DISCONNECT_TIMEOUT GNUNET_TIME_relative_multiply ( \
47  GNUNET_TIME_UNIT_SECONDS, 1)
48 
49 #define ENABLE_PUT GNUNET_YES
50 #define ENABLE_GET GNUNET_YES
51 
52 #include "platform.h"
53 #include "gnunet_util_lib.h"
54 #include "gnunet_protocols.h"
57 /* Just included for the right curl.h */
58 #include "gnunet_curl_lib.h"
59 
60 
61 #define LOG(kind, ...) GNUNET_log_from (kind, PLUGIN_NAME, __VA_ARGS__)
62 
66 struct HTTP_Client_Plugin;
67 
72 {
77 
82 
87 
92 
97 
102 
107 };
108 
112 struct HTTP_Message
113 {
117  struct HTTP_Message *next;
118 
122  struct HTTP_Message *prev;
123 
127  char *buf;
128 
135 
139  void *transmit_cont_cls;
140 
144  size_t pos;
145 
149  size_t size;
150 };
151 
152 
156 struct GNUNET_ATS_Session;
157 
158 
163 struct RequestHandle
164 {
169 
173  CURL *easyhandle;
174 
179 };
180 
181 
185 struct GNUNET_ATS_Session
186 {
190  char *url;
191 
196 
201 
205  struct RequestHandle put;
206 
210  struct RequestHandle get;
211 
215  struct HTTP_Message *msg_head;
216 
220  struct HTTP_Message *msg_tail;
221 
226 
231 
236 
240  struct GNUNET_SCHEDULER_Task *recv_wakeup_task;
241 
246  struct GNUNET_TIME_Absolute next_receive;
247 
252 
256  unsigned long long bytes_in_queue;
257 
262  size_t overhead;
263 
267  unsigned int msgs_in_queue;
268 
273 };
274 
275 
280 {
285 
290 
295 
299  void *sic_cls;
300 
304  char *name;
305 
309  char *protocol;
310 
315 
320 
325 
330 
335 
343  curl_proxytype proxytype;
344 
353 
357  uint32_t options;
358 
363  unsigned int max_requests;
364 
369  unsigned int cur_requests;
370 
374  uint32_t last_tag;
375 
379  uint16_t use_ipv6;
380 
384  uint16_t use_ipv4;
385 
390 };
391 
392 
400 static int
402 
403 
412 static void
414  struct GNUNET_ATS_Session *session,
416 {
417  struct GNUNET_TRANSPORT_SessionInfo info;
418 
419  if (NULL == plugin->sic)
420  return;
421  memset (&info, 0, sizeof(info));
422  info.state = state;
423  info.is_inbound = GNUNET_NO;
424  info.num_msg_pending = session->msgs_in_queue;
425  info.num_bytes_pending = session->bytes_in_queue;
426  info.receive_delay = session->next_receive;
427  info.session_timeout = session->timeout;
428  info.address = session->address;
429  plugin->sic (plugin->sic_cls,
430  session,
431  &info);
432 }
433 
434 
440 static void
442 {
443  struct HTTP_Client_Plugin *plugin = s->plugin;
444  struct HTTP_Message *pos;
445  struct HTTP_Message *next;
446  CURLMcode mret;
447 
448  if (NULL != s->timeout_task)
449  {
451  s->timeout_task = NULL;
453  }
454  if (NULL != s->put_disconnect_task)
455  {
457  s->put_disconnect_task = NULL;
458  }
459  if (NULL != s->recv_wakeup_task)
460  {
462  s->recv_wakeup_task = NULL;
463  }
466  &s->address->peer,
467  s));
468  if (NULL != s->put.easyhandle)
469  {
471  "Session %p/request %p: disconnecting PUT request to peer `%s'\n",
472  s,
473  s->put.easyhandle,
474  GNUNET_i2s (&s->address->peer));
475 
476  /* remove curl handle from multi handle */
477  mret = curl_multi_remove_handle (plugin->curl_multi_handle,
478  s->put.easyhandle);
479  GNUNET_break (CURLM_OK == mret);
480  curl_easy_cleanup (s->put.easyhandle);
481  GNUNET_assert (plugin->cur_requests > 0);
482  plugin->cur_requests--;
483  s->put.easyhandle = NULL;
484  }
485  if (NULL != s->get.easyhandle)
486  {
488  "Session %p/request %p: disconnecting GET request to peer `%s'\n",
489  s, s->get.easyhandle,
490  GNUNET_i2s (&s->address->peer));
491  /* remove curl handle from multi handle */
492  mret = curl_multi_remove_handle (plugin->curl_multi_handle,
493  s->get.easyhandle);
494  GNUNET_break (CURLM_OK == mret);
495  curl_easy_cleanup (s->get.easyhandle);
496  GNUNET_assert (plugin->cur_requests > 0);
497  plugin->cur_requests--;
498  s->get.easyhandle = NULL;
499  }
500 
501  GNUNET_STATISTICS_set (plugin->env->stats,
503  plugin->cur_requests,
504  GNUNET_NO);
505  next = s->msg_head;
506  while (NULL != (pos = next))
507  {
508  next = pos->next;
510  s->msg_tail,
511  pos);
512  GNUNET_assert (0 < s->msgs_in_queue);
513  s->msgs_in_queue--;
514  GNUNET_assert (pos->size <= s->bytes_in_queue);
515  s->bytes_in_queue -= pos->size;
516  if (NULL != pos->transmit_cont)
517  pos->transmit_cont (pos->transmit_cont_cls,
518  &s->address->peer,
520  pos->size,
521  pos->pos + s->overhead);
522  s->overhead = 0;
523  GNUNET_free (pos);
524  }
525  GNUNET_assert (0 == s->msgs_in_queue);
526  GNUNET_assert (0 == s->bytes_in_queue);
527  notify_session_monitor (plugin,
528  s,
530  if (NULL != s->msg_tk)
531  {
533  s->msg_tk = NULL;
534  }
536  GNUNET_free (s->url);
537  GNUNET_free (s);
538 }
539 
540 
546 static void
548 {
549  GNUNET_assert (NULL != s->timeout_task);
552 }
553 
554 
561 static void
562 client_run (void *cls);
563 
564 
572 static int
574  int now)
575 {
576  fd_set rs;
577  fd_set ws;
578  fd_set es;
579  int max;
580  struct GNUNET_NETWORK_FDSet *grs;
581  struct GNUNET_NETWORK_FDSet *gws;
582  long to;
583  CURLMcode mret;
584  struct GNUNET_TIME_Relative timeout;
585 
586  /* Cancel previous scheduled task */
587  if (plugin->client_perform_task != NULL)
588  {
590  plugin->client_perform_task = NULL;
591  }
592  max = -1;
593  FD_ZERO (&rs);
594  FD_ZERO (&ws);
595  FD_ZERO (&es);
596  mret = curl_multi_fdset (plugin->curl_multi_handle, &rs, &ws, &es, &max);
597  if (mret != CURLM_OK)
598  {
600  _ ("%s failed at %s:%d: `%s'\n"),
601  "curl_multi_fdset",
602  __FILE__,
603  __LINE__,
604  curl_multi_strerror (mret));
605  return GNUNET_SYSERR;
606  }
607  mret = curl_multi_timeout (plugin->curl_multi_handle, &to);
608  if (-1 == to)
610  else
612  if (now == GNUNET_YES)
614 
615  if (CURLM_OK != mret)
616  {
618  _ ("%s failed at %s:%d: `%s'\n"),
619  "curl_multi_timeout", __FILE__, __LINE__,
620  curl_multi_strerror (mret));
621  return GNUNET_SYSERR;
622  }
623 
626  GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
627  GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
628 
629  /* Schedule task to run when select is ready to read or write */
630  plugin->client_perform_task =
632  timeout, grs, gws,
633  &client_run, plugin);
636  return GNUNET_OK;
637 }
638 
639 
640 #if VERBOSE_CURL
641 
651 static int
652 client_log (CURL *curl,
653  curl_infotype type,
654  const char *data,
655  size_t size,
656  void *cls)
657 {
658  struct RequestHandle *ch = cls;
659  const char *ttype = "UNSPECIFIED";
660  char text[size + 2];
661 
662  if (! ((CURLINFO_TEXT == type) ||
663  (CURLINFO_HEADER_IN == type) ||
664  (CURLINFO_HEADER_OUT == type)))
665  return 0;
666  switch (type)
667  {
668  case CURLINFO_TEXT:
669  ttype = "TEXT";
670  break;
671 
672  case CURLINFO_HEADER_IN:
673  ttype = "HEADER_IN";
674  break;
675 
676  case CURLINFO_HEADER_OUT:
677  ttype = "HEADER_OUT";
678  /* Overhead*/
679  GNUNET_assert (NULL != ch);
680  GNUNET_assert (NULL != ch->easyhandle);
681  GNUNET_assert (NULL != ch->s);
682  ch->s->overhead += size;
683  break;
684 
685  default:
686  ttype = "UNSPECIFIED";
687  break;
688  }
689  GNUNET_memcpy (text, data, size);
690  if (text[size - 1] == '\n')
691  {
692  text[size] = '\0';
693  }
694  else
695  {
696  text[size] = '\n';
697  text[size + 1] = '\0';
698  }
700  "Request %p %s: %s",
701  ch->easyhandle,
702  ttype,
703  text);
704  return 0;
705 }
706 
707 
708 #endif
709 
716 static int
718 
719 
726 static int
728 
729 
757 static ssize_t
759  struct GNUNET_ATS_Session *s,
760  const char *msgbuf,
761  size_t msgbuf_size,
762  unsigned int priority,
763  struct GNUNET_TIME_Relative to,
765  void *cont_cls)
766 {
767  struct HTTP_Client_Plugin *plugin = cls;
768  struct HTTP_Message *msg;
769  char *stat_txt;
770 
772  "Session %p/request %p: Sending message with %lu to peer `%s' \n",
773  s,
774  s->put.easyhandle,
775  (unsigned long) msgbuf_size,
776  GNUNET_i2s (&s->address->peer));
777 
778  /* create new message and schedule */
779  msg = GNUNET_malloc (sizeof(struct HTTP_Message) + msgbuf_size);
780  msg->size = msgbuf_size;
781  msg->buf = (char *) &msg[1];
782  msg->transmit_cont = cont;
783  msg->transmit_cont_cls = cont_cls;
784  GNUNET_memcpy (msg->buf,
785  msgbuf,
786  msgbuf_size);
788  s->msg_tail,
789  msg);
790  s->msgs_in_queue++;
791  s->bytes_in_queue += msg->size;
792 
793  GNUNET_asprintf (&stat_txt,
794  "# bytes currently in %s_client buffers",
795  plugin->protocol);
797  stat_txt, msgbuf_size, GNUNET_NO);
798  GNUNET_free (stat_txt);
799  notify_session_monitor (plugin,
800  s,
802  if (H_TMP_DISCONNECTING == s->put.state)
803  {
804  /* PUT request is currently getting disconnected */
807  "Session %p/request %p: currently disconnecting, reconnecting immediately\n",
808  s,
809  s->put.easyhandle);
810  return msgbuf_size;
811  }
812  if (H_PAUSED == s->put.state)
813  {
814  /* PUT request was paused, unpause */
815  GNUNET_assert (s->put_disconnect_task != NULL);
817  s->put_disconnect_task = NULL;
819  "Session %p/request %p: unpausing request\n",
820  s, s->put.easyhandle);
821  s->put.state = H_CONNECTED;
822  if (NULL != s->put.easyhandle)
823  curl_easy_pause (s->put.easyhandle, CURLPAUSE_CONT);
824  }
825  else if (H_TMP_DISCONNECTED == s->put.state)
826  {
827  /* PUT request was disconnected, reconnect */
828  LOG (GNUNET_ERROR_TYPE_DEBUG, "Session %p: Reconnecting PUT request\n", s);
829  GNUNET_break (NULL == s->put.easyhandle);
831  {
832  /* Could not reconnect */
834  return GNUNET_SYSERR;
835  }
836  }
838  return msgbuf_size;
839 }
840 
841 
849 static int
851  struct GNUNET_ATS_Session *s)
852 {
853  struct HTTP_Client_Plugin *plugin = cls;
854 
856  "Session %p: notifying transport about ending session\n",
857  s);
858  plugin->env->session_end (plugin->env->cls,
859  s->address,
860  s);
862 
863  /* Re-schedule since handles have changed */
864  if (NULL != plugin->client_perform_task)
865  {
867  plugin->client_perform_task = NULL;
868  }
869  client_schedule (plugin, GNUNET_YES);
870 
871  return GNUNET_OK;
872 }
873 
874 
883 static unsigned int
885 {
886  return 3;
887 }
888 
889 
898 static int
900  const struct GNUNET_PeerIdentity *peer,
901  void *value)
902 {
903  struct HTTP_Client_Plugin *plugin = cls;
904  struct GNUNET_ATS_Session *session = value;
905 
906  http_client_plugin_session_disconnect (plugin, session);
907  return GNUNET_OK;
908 }
909 
910 
919 static void
921  const struct GNUNET_PeerIdentity *target)
922 {
923  struct HTTP_Client_Plugin *plugin = cls;
924 
926  "Transport tells me to disconnect `%s'\n",
927  GNUNET_i2s (target));
929  target,
931  plugin);
932 }
933 
934 
939 {
944 
949 };
950 
951 
960 static int
962  const struct GNUNET_PeerIdentity *key,
963  void *value)
964 {
965  struct GNUNET_ATS_SessionClientCtx *sc_ctx = cls;
966  struct GNUNET_ATS_Session *s = value;
967 
968  if (0 == GNUNET_HELLO_address_cmp (sc_ctx->address,
969  s->address))
970  {
971  sc_ctx->ret = s;
972  return GNUNET_NO;
973  }
974  return GNUNET_YES;
975 }
976 
977 
985 static struct GNUNET_ATS_Session *
987  const struct GNUNET_HELLO_Address *address)
988 {
989  struct GNUNET_ATS_SessionClientCtx sc_ctx;
990 
991  sc_ctx.address = address;
992  sc_ctx.ret = NULL;
995  &sc_ctx);
996  return sc_ctx.ret;
997 }
998 
999 
1007 static void
1009 {
1010  struct GNUNET_ATS_Session *s = cls;
1011 
1012  s->put_disconnect_task = NULL;
1014  "Session %p/request %p: will be disconnected due to no activity\n",
1015  s, s->put.easyhandle);
1017  if (NULL != s->put.easyhandle)
1018  curl_easy_pause (s->put.easyhandle,
1019  CURLPAUSE_CONT);
1021 }
1022 
1023 
1034 static size_t
1035 client_send_cb (void *stream,
1036  size_t size,
1037  size_t nmemb,
1038  void *cls)
1039 {
1040  struct GNUNET_ATS_Session *s = cls;
1041  struct HTTP_Client_Plugin *plugin = s->plugin;
1042  struct HTTP_Message *msg = s->msg_head;
1043  size_t len;
1044  char *stat_txt;
1045 
1046  if (H_TMP_DISCONNECTING == s->put.state)
1047  {
1049  "Session %p/request %p: disconnect due to inactivity\n",
1050  s, s->put.easyhandle);
1051  return 0;
1052  }
1053 
1054  if (NULL == msg)
1055  {
1056  if (GNUNET_YES == plugin->emulate_xhr)
1057  {
1059  "Session %p/request %p: PUT request finished\n",
1060  s,
1061  s->put.easyhandle);
1063  return 0;
1064  }
1065 
1066  /* We have nothing to send, so pause PUT request */
1068  "Session %p/request %p: nothing to send, suspending\n",
1069  s,
1070  s->put.easyhandle);
1074  s);
1075  s->put.state = H_PAUSED;
1076  return CURL_READFUNC_PAUSE;
1077  }
1078  /* data to send */
1079  GNUNET_assert (msg->pos < msg->size);
1080  /* calculate how much fits in buffer */
1081  len = GNUNET_MIN (msg->size - msg->pos,
1082  size * nmemb);
1083  GNUNET_memcpy (stream,
1084  &msg->buf[msg->pos],
1085  len);
1086  msg->pos += len;
1087  if (msg->pos == msg->size)
1088  {
1090  "Session %p/request %p: sent message with %lu bytes sent, removing message from queue\n",
1091  s,
1092  s->put.easyhandle,
1093  (unsigned long) msg->size);
1094  /* Calling transmit continuation */
1096  s->msg_tail,
1097  msg);
1098  GNUNET_assert (0 < s->msgs_in_queue);
1099  s->msgs_in_queue--;
1100  GNUNET_assert (msg->size <= s->bytes_in_queue);
1101  s->bytes_in_queue -= msg->size;
1102  if (NULL != msg->transmit_cont)
1103  msg->transmit_cont (msg->transmit_cont_cls,
1104  &s->address->peer,
1105  GNUNET_OK,
1106  msg->size,
1107  msg->size + s->overhead);
1108  s->overhead = 0;
1109  GNUNET_free (msg);
1110  }
1111  notify_session_monitor (plugin,
1112  s,
1114  GNUNET_asprintf (&stat_txt,
1115  "# bytes currently in %s_client buffers",
1116  plugin->protocol);
1118  stat_txt,
1119  -len,
1120  GNUNET_NO);
1121  GNUNET_free (stat_txt);
1122  GNUNET_asprintf (&stat_txt,
1123  "# bytes transmitted via %s_client",
1124  plugin->protocol);
1126  stat_txt,
1127  len,
1128  GNUNET_NO);
1129  GNUNET_free (stat_txt);
1130  return len;
1131 }
1132 
1133 
1139 static void
1140 client_wake_up (void *cls)
1141 {
1142  struct GNUNET_ATS_Session *s = cls;
1143 
1144  s->recv_wakeup_task = NULL;
1146  "Session %p/request %p: Waking up GET handle\n",
1147  s, s->get.easyhandle);
1148  if (H_PAUSED == s->put.state)
1149  {
1150  /* PUT request was paused, unpause */
1151  GNUNET_assert (s->put_disconnect_task != NULL);
1153  s->put_disconnect_task = NULL;
1154  s->put.state = H_CONNECTED;
1155  if (NULL != s->put.easyhandle)
1156  curl_easy_pause (s->put.easyhandle, CURLPAUSE_CONT);
1157  }
1158  if (NULL != s->get.easyhandle)
1159  curl_easy_pause (s->get.easyhandle, CURLPAUSE_CONT);
1160 }
1161 
1162 
1170 static int
1172  const struct GNUNET_MessageHeader *message)
1173 {
1174  struct GNUNET_ATS_Session *s = cls;
1175  struct HTTP_Client_Plugin *plugin;
1176  struct GNUNET_TIME_Relative delay;
1177  char *stat_txt;
1178 
1179  plugin = s->plugin;
1180  delay = s->plugin->env->receive (plugin->env->cls,
1181  s->address,
1182  s,
1183  message);
1184  GNUNET_asprintf (&stat_txt,
1185  "# bytes received via %s_client",
1186  plugin->protocol);
1188  stat_txt,
1189  ntohs (message->size),
1190  GNUNET_NO);
1191  GNUNET_free (stat_txt);
1192 
1194  if (GNUNET_TIME_absolute_get ().abs_value_us < s->next_receive.abs_value_us)
1195  {
1197  "Client: peer `%s' address `%s' next read delayed for %s\n",
1198  GNUNET_i2s (&s->address->peer),
1200  s->address->address,
1201  s->address->address_length),
1203  GNUNET_YES));
1204  }
1206  return GNUNET_OK;
1207 }
1208 
1209 
1220 static size_t
1221 client_receive_put (void *stream,
1222  size_t size,
1223  size_t nmemb,
1224  void *cls)
1225 {
1226  return size * nmemb;
1227 }
1228 
1229 
1240 static size_t
1241 client_receive (void *stream,
1242  size_t size,
1243  size_t nmemb,
1244  void *cls)
1245 {
1246  struct GNUNET_ATS_Session *s = cls;
1247  struct GNUNET_TIME_Absolute now;
1248  size_t len = size * nmemb;
1249 
1251  "Session %p / request %p: Received %lu bytes from peer `%s'\n",
1252  s,
1253  s->get.easyhandle,
1254  (unsigned long) len,
1255  GNUNET_i2s (&s->address->peer));
1256  now = GNUNET_TIME_absolute_get ();
1257  if (now.abs_value_us < s->next_receive.abs_value_us)
1258  {
1260  struct GNUNET_TIME_Relative delta
1262 
1264  "Session %p / request %p: No inbound bandwidth available! Next read was delayed for %s\n",
1265  s,
1266  s->get.easyhandle,
1268  GNUNET_YES));
1269  if (s->recv_wakeup_task != NULL)
1270  {
1272  s->recv_wakeup_task = NULL;
1273  }
1274  s->recv_wakeup_task
1276  &client_wake_up,
1277  s);
1278  return CURL_WRITEFUNC_PAUSE;
1279  }
1280  if (NULL == s->msg_tk)
1282  s);
1284  stream,
1285  len,
1286  GNUNET_NO,
1287  GNUNET_NO);
1288  return len;
1289 }
1290 
1291 
1297 static void
1298 client_run (void *cls)
1299 {
1300  struct HTTP_Client_Plugin *plugin = cls;
1301  int running;
1302  long http_statuscode;
1303  CURLMcode mret;
1304  CURLMsg *msg;
1305  int put_request; /* GNUNET_YES if easy handle is put, GNUNET_NO for get */
1306  int msgs_left;
1307 
1308  plugin->client_perform_task = NULL;
1309  /* While data are available or timeouts occured */
1310  do
1311  {
1312  running = 0;
1313  /* Perform operations for all handles */
1314  mret = curl_multi_perform (plugin->curl_multi_handle, &running);
1315 
1316  /* Get additional information for all handles */
1317  while (NULL != (msg = curl_multi_info_read (plugin->curl_multi_handle,
1318  &msgs_left)))
1319  {
1320  CURL *easy_h = msg->easy_handle;
1321  struct GNUNET_ATS_Session *s = NULL;
1322  char *d = NULL; /* curl requires 'd' to be a 'char *' */
1323 
1324  GNUNET_assert (NULL != easy_h);
1325 
1326  /* Obtain session from easy handle */
1327  GNUNET_assert (CURLE_OK == curl_easy_getinfo (easy_h, CURLINFO_PRIVATE,
1328  &d));
1329  s = (struct GNUNET_ATS_Session *) d;
1330  GNUNET_assert (NULL != s);
1331 
1332  if (msg->msg != CURLMSG_DONE)
1333  continue; /* This should not happen */
1334 
1335  /* Get HTTP response code */
1336  GNUNET_break (CURLE_OK == curl_easy_getinfo (easy_h,
1337  CURLINFO_RESPONSE_CODE,
1338  &http_statuscode));
1339 
1340  if (easy_h == s->put.easyhandle)
1341  put_request = GNUNET_YES;
1342  else
1343  put_request = GNUNET_NO;
1344 
1345  /* Log status of terminated request */
1346  if ((0 != msg->data.result) || (http_statuscode != 200))
1348  "Session %p/request %p: %s request to `%s' ended with status %li reason %i: `%s'\n",
1349  s, msg->easy_handle,
1350  (GNUNET_YES == put_request) ? "PUT" : "GET",
1351  GNUNET_i2s (&s->address->peer),
1352  http_statuscode,
1353  msg->data.result,
1354  curl_easy_strerror (msg->data.result));
1355  else
1357  "Session %p/request %p: %s request to `%s' ended normal\n",
1358  s, msg->easy_handle,
1359  (GNUNET_YES == put_request) ? "PUT" : "GET",
1360  GNUNET_i2s (&s->address->peer));
1361 
1362  /* Remove easy handle from multi handle */
1363  curl_multi_remove_handle (plugin->curl_multi_handle, easy_h);
1364 
1365  /* Clean up easy handle */
1366  curl_easy_cleanup (easy_h);
1367 
1368  /* Remove information */
1369  GNUNET_assert (plugin->cur_requests > 0);
1370  plugin->cur_requests--;
1372  "%s request to %s done, number of requests decreased to %u\n",
1373  (GNUNET_YES == put_request) ? "PUT" : "GET",
1374  s->url,
1375  plugin->cur_requests);
1376 
1377  if (GNUNET_YES == put_request)
1378  {
1379  /* Clean up a PUT request */
1380  s->put.easyhandle = NULL;
1381  s->put.s = NULL;
1382 
1383  switch (s->put.state)
1384  {
1385  case H_NOT_CONNECTED:
1386  case H_DISCONNECTED:
1387  case H_TMP_DISCONNECTED:
1388  /* This must not happen */
1389  GNUNET_break (0);
1390  break;
1391 
1393  /* Transport called send while disconnect in progess, reconnect */
1394  if (GNUNET_SYSERR == client_connect_put (s))
1395  {
1396  /* Reconnect failed, disconnect session */
1398  }
1399  break;
1400 
1401  case H_TMP_DISCONNECTING:
1402  /* PUT gets temporarily disconnected */
1404  break;
1405 
1406  case H_PAUSED:
1407  case H_CONNECTED:
1408  /* PUT gets permanently disconnected */
1409  s->put.state = H_DISCONNECTED;
1411  break;
1412 
1413  default:
1414  GNUNET_break (0);
1415  break;
1416  }
1417  }
1418  else if (GNUNET_NO == put_request)
1419  {
1420  /* Clean up a GET request */
1421  s->get.easyhandle = NULL;
1422  s->get.s = NULL;
1423 
1424  /* If we are emulating an XHR client we need to make another GET
1425  * request.
1426  */
1427  if (GNUNET_YES == plugin->emulate_xhr)
1428  {
1429  if (GNUNET_SYSERR == client_connect_get (s))
1431  }
1432  else
1433  {
1434  /* GET request was terminated, so disconnect session */
1436  }
1437  }
1438  else
1439  GNUNET_break (0); /* Must not happen */
1440 
1441  GNUNET_STATISTICS_set (plugin->env->stats,
1443  plugin->cur_requests,
1444  GNUNET_NO);
1445  }
1446  }
1447  while (mret == CURLM_CALL_MULTI_PERFORM);
1448  client_schedule (plugin, GNUNET_NO);
1449 }
1450 
1451 
1452 #ifdef TCP_STEALTH
1453 
1461 static curl_socket_t
1462 open_tcp_stealth_socket_cb (void *clientp,
1463  curlsocktype purpose,
1464  struct curl_sockaddr *address)
1465 {
1466  struct GNUNET_ATS_Session *s = clientp;
1467  int ret;
1468 
1469  switch (purpose)
1470  {
1471  case CURLSOCKTYPE_IPCXN:
1472  ret = socket (address->family,
1473  address->socktype,
1474  address->protocol);
1475  if (-1 == ret)
1476  return CURL_SOCKET_BAD;
1477  if (((SOCK_STREAM != address->socktype) ||
1478  ((0 != address->protocol) &&
1479  (IPPROTO_TCP != address->protocol))))
1480  return (curl_socket_t) ret;
1481  if ((0 != setsockopt (ret,
1482  IPPROTO_TCP,
1483  TCP_STEALTH,
1484  &s->address->peer,
1485  sizeof(struct GNUNET_PeerIdentity))))
1486  {
1488  _ ("TCP_STEALTH not supported on this platform.\n"));
1489  (void) close (ret);
1490  return CURL_SOCKET_BAD;
1491  }
1492  return (curl_socket_t) ret;
1493 
1494  case CURLSOCKTYPE_ACCEPT:
1495  GNUNET_break (0);
1496  return CURL_SOCKET_BAD;
1497  break;
1498 
1499  case CURLSOCKTYPE_LAST:
1500  GNUNET_break (0);
1501  return CURL_SOCKET_BAD;
1502 
1503  default:
1504  GNUNET_break (0);
1505  return CURL_SOCKET_BAD;
1506  }
1507 }
1508 
1509 
1510 #endif
1511 
1512 
1519 static int
1521 {
1522  CURLMcode mret;
1523  struct HttpAddress *ha;
1524  uint32_t options;
1525 
1526  ha = (struct HttpAddress *) s->address->address;
1527  options = ntohl (ha->options);
1528  /* create get request */
1529  s->get.easyhandle = curl_easy_init ();
1530  s->get.s = s;
1531  if (0 != (options & HTTP_OPTIONS_TCP_STEALTH))
1532  {
1533 #ifdef TCP_STEALTH
1534  curl_easy_setopt (s->get.easyhandle,
1535  CURLOPT_OPENSOCKETFUNCTION,
1536  &open_tcp_stealth_socket_cb);
1537  curl_easy_setopt (s->get.easyhandle,
1538  CURLOPT_OPENSOCKETDATA,
1539  s);
1540 #else
1542  "Cannot connect, TCP STEALTH needed and not supported by kernel.\n");
1543  curl_easy_cleanup (s->get.easyhandle);
1544  s->get.easyhandle = NULL;
1545  s->get.s = NULL;
1546  return GNUNET_SYSERR;
1547 #endif
1548  }
1549 
1550 #if VERBOSE_CURL
1551  curl_easy_setopt (s->get.easyhandle,
1552  CURLOPT_VERBOSE,
1553  1L);
1554  curl_easy_setopt (s->get.easyhandle,
1555  CURLOPT_DEBUGFUNCTION,
1556  &client_log);
1557  curl_easy_setopt (s->get.easyhandle,
1558  CURLOPT_DEBUGDATA,
1559  &s->get);
1560 #endif
1561 #if BUILD_HTTPS
1562  curl_easy_setopt (s->get.easyhandle, CURLOPT_SSLVERSION,
1563  CURL_SSLVERSION_TLSv1);
1564  {
1566  (options & HTTP_OPTIONS_VERIFY_CERTIFICATE))
1567  {
1568  curl_easy_setopt (s->get.easyhandle,
1569  CURLOPT_SSL_VERIFYPEER, 1L);
1570  curl_easy_setopt (s->get.easyhandle,
1571  CURLOPT_SSL_VERIFYHOST,
1572  2L);
1573  }
1574  else
1575  {
1576  curl_easy_setopt (s->get.easyhandle,
1577  CURLOPT_SSL_VERIFYPEER,
1578  0L);
1579  curl_easy_setopt (s->get.easyhandle,
1580  CURLOPT_SSL_VERIFYHOST,
1581  0L);
1582  }
1583  }
1584  curl_easy_setopt (s->get.easyhandle,
1585  CURLOPT_PROTOCOLS,
1586  CURLPROTO_HTTPS);
1587  curl_easy_setopt (s->get.easyhandle,
1588  CURLOPT_REDIR_PROTOCOLS,
1589  CURLPROTO_HTTPS);
1590 #else
1591  curl_easy_setopt (s->get.easyhandle,
1592  CURLOPT_PROTOCOLS,
1593  CURLPROTO_HTTP);
1594  curl_easy_setopt (s->get.easyhandle,
1595  CURLOPT_REDIR_PROTOCOLS,
1596  CURLPROTO_HTTP);
1597 #endif
1598 
1599  if (NULL != s->plugin->proxy_hostname)
1600  {
1601  curl_easy_setopt (s->get.easyhandle,
1602  CURLOPT_PROXY,
1603  s->plugin->proxy_hostname);
1604  curl_easy_setopt (s->get.easyhandle,
1605  CURLOPT_PROXYTYPE,
1606  s->plugin->proxytype);
1607  if (NULL != s->plugin->proxy_username)
1608  curl_easy_setopt (s->get.easyhandle,
1609  CURLOPT_PROXYUSERNAME,
1610  s->plugin->proxy_username);
1611  if (NULL != s->plugin->proxy_password)
1612  curl_easy_setopt (s->get.easyhandle,
1613  CURLOPT_PROXYPASSWORD,
1614  s->plugin->proxy_password);
1615  if (GNUNET_YES == s->plugin->proxy_use_httpproxytunnel)
1616  curl_easy_setopt (s->get.easyhandle,
1617  CURLOPT_HTTPPROXYTUNNEL,
1618  s->plugin->proxy_use_httpproxytunnel);
1619  }
1620 
1621  if (GNUNET_YES == s->plugin->emulate_xhr)
1622  {
1623  char *url;
1624 
1625  GNUNET_asprintf (&url,
1626  "%s,1",
1627  s->url);
1628  curl_easy_setopt (s->get.easyhandle,
1629  CURLOPT_URL,
1630  url);
1631  GNUNET_free (url);
1632  }
1633  else
1634  {
1635  curl_easy_setopt (s->get.easyhandle,
1636  CURLOPT_URL,
1637  s->url);
1638  }
1639  curl_easy_setopt (s->get.easyhandle,
1640  CURLOPT_READFUNCTION,
1641  &client_send_cb);
1642  curl_easy_setopt (s->get.easyhandle,
1643  CURLOPT_READDATA,
1644  s);
1645  curl_easy_setopt (s->get.easyhandle,
1646  CURLOPT_WRITEFUNCTION,
1647  &client_receive);
1648  curl_easy_setopt (s->get.easyhandle,
1649  CURLOPT_WRITEDATA,
1650  s);
1651  /* No timeout by default, timeout done with session timeout */
1652  curl_easy_setopt (s->get.easyhandle,
1653  CURLOPT_TIMEOUT,
1654  0L);
1655  curl_easy_setopt (s->get.easyhandle,
1656  CURLOPT_PRIVATE, s);
1657  curl_easy_setopt (s->get.easyhandle,
1658  CURLOPT_CONNECTTIMEOUT_MS,
1659  (long) (HTTP_CLIENT_NOT_VALIDATED_TIMEOUT.rel_value_us
1660  / 1000LL));
1661  curl_easy_setopt (s->get.easyhandle, CURLOPT_BUFFERSIZE,
1663 #if CURL_TCP_NODELAY
1664  curl_easy_setopt (ps->recv_endpoint,
1665  CURLOPT_TCP_NODELAY,
1666  1L);
1667 #endif
1668  curl_easy_setopt (s->get.easyhandle,
1669  CURLOPT_FOLLOWLOCATION,
1670  0L);
1671 
1672  mret = curl_multi_add_handle (s->plugin->curl_multi_handle,
1673  s->get.easyhandle);
1674  if (CURLM_OK != mret)
1675  {
1677  "Session %p : Failed to add GET handle to multihandle: `%s'\n",
1678  s,
1679  curl_multi_strerror (mret));
1680  curl_easy_cleanup (s->get.easyhandle);
1681  s->get.easyhandle = NULL;
1682  s->get.s = NULL;
1683  GNUNET_break (0);
1684  return GNUNET_SYSERR;
1685  }
1686  s->plugin->cur_requests++;
1688  "GET request `%s' established, number of requests increased to %u\n",
1689  s->url,
1690  s->plugin->cur_requests);
1691  return GNUNET_OK;
1692 }
1693 
1694 
1701 static int
1703 {
1704  CURLMcode mret;
1705  struct HttpAddress *ha;
1706  uint32_t options;
1707 
1708  ha = (struct HttpAddress *) s->address->address;
1709  options = ntohl (ha->options);
1710  /* create put request */
1712  "Session %p: Init PUT handle\n",
1713  s);
1714  s->put.easyhandle = curl_easy_init ();
1715  s->put.s = s;
1716 #if VERBOSE_CURL
1717  curl_easy_setopt (s->put.easyhandle,
1718  CURLOPT_VERBOSE,
1719  1L);
1720  curl_easy_setopt (s->put.easyhandle,
1721  CURLOPT_DEBUGFUNCTION,
1722  &client_log);
1723  curl_easy_setopt (s->put.easyhandle,
1724  CURLOPT_DEBUGDATA,
1725  &s->put);
1726 #endif
1727  if (0 != (options & HTTP_OPTIONS_TCP_STEALTH))
1728  {
1729 #ifdef TCP_STEALTH
1730  curl_easy_setopt (s->put.easyhandle,
1731  CURLOPT_OPENSOCKETFUNCTION,
1732  &open_tcp_stealth_socket_cb);
1733  curl_easy_setopt (s->put.easyhandle,
1734  CURLOPT_OPENSOCKETDATA,
1735  s);
1736 #else
1738  "Cannot connect, TCP STEALTH needed and not supported by kernel.\n");
1739  curl_easy_cleanup (s->put.easyhandle);
1740  s->put.easyhandle = NULL;
1741  s->put.s = NULL;
1742  s->put.state = H_DISCONNECTED;
1743  return GNUNET_SYSERR;
1744 #endif
1745  }
1746 #if BUILD_HTTPS
1747  curl_easy_setopt (s->put.easyhandle,
1748  CURLOPT_SSLVERSION,
1749  CURL_SSLVERSION_TLSv1);
1750  {
1751  struct HttpAddress *ha;
1752  ha = (struct HttpAddress *) s->address->address;
1753 
1755  (ntohl (ha->options) & HTTP_OPTIONS_VERIFY_CERTIFICATE))
1756  {
1757  curl_easy_setopt (s->put.easyhandle,
1758  CURLOPT_SSL_VERIFYPEER,
1759  1L);
1760  curl_easy_setopt (s->put.easyhandle,
1761  CURLOPT_SSL_VERIFYHOST,
1762  2L);
1763  }
1764  else
1765  {
1766  curl_easy_setopt (s->put.easyhandle,
1767  CURLOPT_SSL_VERIFYPEER,
1768  0L);
1769  curl_easy_setopt (s->put.easyhandle,
1770  CURLOPT_SSL_VERIFYHOST,
1771  0L);
1772  }
1773  }
1774  curl_easy_setopt (s->put.easyhandle,
1775  CURLOPT_PROTOCOLS,
1776  CURLPROTO_HTTPS);
1777  curl_easy_setopt (s->put.easyhandle,
1778  CURLOPT_REDIR_PROTOCOLS,
1779  CURLPROTO_HTTPS);
1780 #else
1781  curl_easy_setopt (s->put.easyhandle,
1782  CURLOPT_PROTOCOLS,
1783  CURLPROTO_HTTP);
1784  curl_easy_setopt (s->put.easyhandle,
1785  CURLOPT_REDIR_PROTOCOLS,
1786  CURLPROTO_HTTP);
1787 #endif
1788  if (NULL != s->plugin->proxy_hostname)
1789  {
1790  curl_easy_setopt (s->put.easyhandle,
1791  CURLOPT_PROXY,
1792  s->plugin->proxy_hostname);
1793  curl_easy_setopt (s->put.easyhandle,
1794  CURLOPT_PROXYTYPE,
1795  s->plugin->proxytype);
1796  if (NULL != s->plugin->proxy_username)
1797  curl_easy_setopt (s->put.easyhandle,
1798  CURLOPT_PROXYUSERNAME,
1799  s->plugin->proxy_username);
1800  if (NULL != s->plugin->proxy_password)
1801  curl_easy_setopt (s->put.easyhandle,
1802  CURLOPT_PROXYPASSWORD,
1803  s->plugin->proxy_password);
1804  if (GNUNET_YES == s->plugin->proxy_use_httpproxytunnel)
1805  curl_easy_setopt (s->put.easyhandle,
1806  CURLOPT_HTTPPROXYTUNNEL,
1807  s->plugin->proxy_use_httpproxytunnel);
1808  }
1809 
1810  curl_easy_setopt (s->put.easyhandle,
1811  CURLOPT_URL,
1812  s->url);
1813  curl_easy_setopt (s->put.easyhandle,
1814  CURLOPT_UPLOAD,
1815  1L);
1816  curl_easy_setopt (s->put.easyhandle,
1817  CURLOPT_READFUNCTION,
1818  &client_send_cb);
1819  curl_easy_setopt (s->put.easyhandle,
1820  CURLOPT_READDATA,
1821  s);
1822  curl_easy_setopt (s->put.easyhandle,
1823  CURLOPT_WRITEFUNCTION,
1825  curl_easy_setopt (s->put.easyhandle,
1826  CURLOPT_WRITEDATA,
1827  s);
1828  /* No timeout by default, timeout done with session timeout */
1829  curl_easy_setopt (s->put.easyhandle,
1830  CURLOPT_TIMEOUT,
1831  0L);
1832  curl_easy_setopt (s->put.easyhandle,
1833  CURLOPT_PRIVATE,
1834  s);
1835  curl_easy_setopt (s->put.easyhandle,
1836  CURLOPT_CONNECTTIMEOUT_MS,
1837  (long) (HTTP_CLIENT_NOT_VALIDATED_TIMEOUT.rel_value_us
1838  / 1000LL));
1839  curl_easy_setopt (s->put.easyhandle, CURLOPT_BUFFERSIZE,
1841 #if CURL_TCP_NODELAY
1842  curl_easy_setopt (s->put.easyhandle, CURLOPT_TCP_NODELAY, 1);
1843 #endif
1844  mret = curl_multi_add_handle (s->plugin->curl_multi_handle,
1845  s->put.easyhandle);
1846  if (CURLM_OK != mret)
1847  {
1849  "Session %p : Failed to add PUT handle to multihandle: `%s'\n",
1850  s, curl_multi_strerror (mret));
1851  curl_easy_cleanup (s->put.easyhandle);
1852  s->put.easyhandle = NULL;
1853  s->put.s = NULL;
1854  s->put.state = H_DISCONNECTED;
1855  return GNUNET_SYSERR;
1856  }
1857  s->put.state = H_CONNECTED;
1858  s->plugin->cur_requests++;
1859 
1861  "PUT request `%s' established, number of requests increased to %u\n",
1862  s->url, s->plugin->cur_requests);
1863 
1864  return GNUNET_OK;
1865 }
1866 
1867 
1874 static int
1876 {
1877  struct HTTP_Client_Plugin *plugin = s->plugin;
1878  int res = GNUNET_OK;
1879 
1880  /* create url */
1881  if (NULL ==
1883  s->address->address,
1884  s->address->address_length))
1885  {
1887  "Invalid address peer `%s'\n",
1888  GNUNET_i2s (&s->address->peer));
1889  return GNUNET_SYSERR;
1890  }
1891 
1892  GNUNET_asprintf (&s->url,
1893  "%s/%s;%u",
1895  s->address->address,
1896  s->address->address_length),
1897  GNUNET_i2s_full (plugin->env->my_identity),
1898  plugin->last_tag);
1899 
1900  plugin->last_tag++;
1902  "Initiating outbound session peer `%s' using address `%s'\n",
1903  GNUNET_i2s (&s->address->peer), s->url);
1904 
1905  if (GNUNET_SYSERR == client_connect_get (s))
1906  return GNUNET_SYSERR;
1907  /* If we are emulating an XHR client then delay sending a PUT request until
1908  * there is something to send.
1909  */
1910  if (GNUNET_YES == plugin->emulate_xhr)
1911  {
1913  }
1914  else if (GNUNET_SYSERR == client_connect_put (s))
1915  return GNUNET_SYSERR;
1916 
1918  "Session %p: connected with GET %p and PUT %p\n",
1919  s, s->get.easyhandle,
1920  s->put.easyhandle);
1921  /* Perform connect */
1922  GNUNET_STATISTICS_set (plugin->env->stats,
1924  plugin->cur_requests,
1925  GNUNET_NO);
1926  /* Re-schedule since handles have changed */
1927  if (NULL != plugin->client_perform_task)
1928  {
1930  plugin->client_perform_task = NULL;
1931  }
1932 
1933  /* Schedule task to run immediately */
1935  plugin);
1936  return res;
1937 }
1938 
1939 
1947 static enum GNUNET_NetworkType
1949  struct GNUNET_ATS_Session *session)
1950 {
1951  return session->scope;
1952 }
1953 
1954 
1962 static enum GNUNET_NetworkType
1964  const struct
1966 {
1967  struct HTTP_Client_Plugin *plugin = cls;
1968 
1969  return http_common_get_network_for_address (plugin->env,
1970  address);
1971 }
1972 
1973 
1979 static void
1981 {
1982  struct GNUNET_ATS_Session *s = cls;
1983  struct GNUNET_TIME_Relative left;
1984 
1985  s->timeout_task = NULL;
1987  if (0 != left.rel_value_us)
1988  {
1989  /* not actually our turn yet, but let's at least update
1990  the monitor, it may think we're about to die ... */
1992  s,
1996  s);
1997  return;
1998  }
1999  LOG (TIMEOUT_LOG,
2000  "Session %p was idle for %s, disconnecting\n",
2001  s,
2003  GNUNET_YES));
2006  s));
2007 }
2008 
2009 
2018 static struct GNUNET_ATS_Session *
2020  const struct GNUNET_HELLO_Address *address)
2021 {
2022  struct HTTP_Client_Plugin *plugin = cls;
2023  struct GNUNET_ATS_Session *s;
2024  struct sockaddr *sa;
2025  enum GNUNET_NetworkType net_type;
2026  size_t salen = 0;
2027  int res;
2028 
2029  GNUNET_assert (NULL != address->address);
2030 
2031  /* find existing session */
2032  s = client_lookup_session (plugin, address);
2033  if (NULL != s)
2034  return s;
2035 
2036  /* create a new session */
2037  if (plugin->max_requests <= plugin->cur_requests)
2038  {
2040  "Maximum number of requests (%u) reached: "
2041  "cannot connect to peer `%s'\n",
2042  plugin->max_requests,
2043  GNUNET_i2s (&address->peer));
2044  return NULL;
2045  }
2046 
2047  /* Determine network location */
2048  net_type = GNUNET_NT_UNSPECIFIED;
2050  address->address_length,
2051  &res);
2052  if (GNUNET_SYSERR == res)
2053  return NULL;
2054  if (GNUNET_YES == res)
2055  {
2056  GNUNET_assert (NULL != sa);
2057  if (AF_INET == sa->sa_family)
2058  {
2059  salen = sizeof(struct sockaddr_in);
2060  }
2061  else if (AF_INET6 == sa->sa_family)
2062  {
2063  salen = sizeof(struct sockaddr_in6);
2064  }
2065  net_type = plugin->env->get_address_type (plugin->env->cls, sa, salen);
2066  GNUNET_free (sa);
2067  }
2068  else if (GNUNET_NO == res)
2069  {
2070  /* Cannot convert to sockaddr -> is external hostname */
2071  net_type = GNUNET_NT_WAN;
2072  }
2073  if (GNUNET_NT_UNSPECIFIED == net_type)
2074  {
2075  GNUNET_break (0);
2076  return NULL;
2077  }
2078 
2079  s = GNUNET_new (struct GNUNET_ATS_Session);
2080  s->plugin = plugin;
2081  s->address = GNUNET_HELLO_address_copy (address);
2082  s->scope = net_type;
2083 
2084  s->put.state = H_NOT_CONNECTED;
2088  s);
2090  "Created new session %p for `%s' address `%s''\n",
2091  s,
2093  s->address->address,
2094  s->address->address_length),
2095  GNUNET_i2s (&s->address->peer));
2096 
2097  /* add new session */
2099  &s->address->peer,
2100  s,
2102  /* initiate new connection */
2103  if (GNUNET_SYSERR == client_connect (s))
2104  {
2106  "Cannot connect to peer `%s' address `%s''\n",
2108  s->address->address,
2109  s->address->address_length),
2110  GNUNET_i2s (&s->address->peer));
2112  return NULL;
2113  }
2114  notify_session_monitor (plugin,
2115  s,
2117  notify_session_monitor (plugin,
2118  s,
2119  GNUNET_TRANSPORT_SS_UP); /* or handshake? */
2120  return s;
2121 }
2122 
2123 
2130 static int
2132 {
2133  curl_global_init (CURL_GLOBAL_ALL);
2134  plugin->curl_multi_handle = curl_multi_init ();
2135 
2136  if (NULL == plugin->curl_multi_handle)
2137  {
2139  _ (
2140  "Could not initialize curl multi handle, failed to start %s plugin!\n"),
2141  plugin->name);
2142  return GNUNET_SYSERR;
2143  }
2144  return GNUNET_OK;
2145 }
2146 
2147 
2160 static int
2162  const void *addr,
2163  size_t addrlen)
2164 {
2165  /* A HTTP/S client does not have any valid address so:*/
2166  return GNUNET_NO;
2167 }
2168 
2169 
2176 void *
2178 {
2179  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2180  struct HTTP_Client_Plugin *plugin = api->cls;
2181 
2182  if (NULL == api->cls)
2183  {
2184  /* Stub shutdown */
2185  GNUNET_free (api);
2186  return NULL;
2187  }
2189  _ ("Shutting down plugin `%s'\n"),
2190  plugin->name);
2193  plugin);
2194  if (NULL != plugin->client_perform_task)
2195  {
2197  plugin->client_perform_task = NULL;
2198  }
2199  if (NULL != plugin->curl_multi_handle)
2200  {
2201  curl_multi_cleanup (plugin->curl_multi_handle);
2202  plugin->curl_multi_handle = NULL;
2203  }
2204  curl_global_cleanup ();
2206  _ ("Shutdown for plugin `%s' complete\n"),
2207  plugin->name);
2209  GNUNET_free (plugin->proxy_hostname);
2210  GNUNET_free (plugin->proxy_username);
2211  GNUNET_free (plugin->proxy_password);
2212  GNUNET_free (plugin);
2213  GNUNET_free (api);
2214  return NULL;
2215 }
2216 
2217 
2224 static int
2226 {
2227  unsigned long long max_requests;
2228  char *proxy_type;
2229 
2230  /* Optional parameters */
2231  if (GNUNET_OK !=
2233  plugin->name,
2234  "MAX_CONNECTIONS",
2235  &max_requests))
2236  max_requests = 128;
2237  plugin->max_requests = max_requests;
2238 
2240  _ ("Maximum number of requests is %u\n"),
2241  plugin->max_requests);
2242 
2243  /* Read proxy configuration */
2244  if (GNUNET_OK ==
2246  plugin->name,
2247  "PROXY",
2248  &plugin->proxy_hostname))
2249  {
2251  "Found proxy host: `%s'\n",
2252  plugin->proxy_hostname);
2253  /* proxy username */
2254  if (GNUNET_OK ==
2256  plugin->name,
2257  "PROXY_USERNAME",
2258  &plugin->proxy_username))
2259  {
2261  "Found proxy username name: `%s'\n",
2262  plugin->proxy_username);
2263  }
2264 
2265  /* proxy password */
2266  if (GNUNET_OK ==
2268  plugin->name,
2269  "PROXY_PASSWORD",
2270  &plugin->proxy_password))
2271  {
2273  "Found proxy password name: `%s'\n",
2274  plugin->proxy_password);
2275  }
2276 
2277  /* proxy type */
2278  if (GNUNET_OK ==
2280  plugin->name,
2281  "PROXY_TYPE",
2282  &proxy_type))
2283  {
2284  GNUNET_STRINGS_utf8_toupper (proxy_type, proxy_type);
2285 
2286  if (0 == strcmp (proxy_type, "HTTP"))
2287  plugin->proxytype = CURLPROXY_HTTP;
2288  else if (0 == strcmp (proxy_type, "SOCKS4"))
2289  plugin->proxytype = CURLPROXY_SOCKS4;
2290  else if (0 == strcmp (proxy_type, "SOCKS5"))
2291  plugin->proxytype = CURLPROXY_SOCKS5;
2292  else if (0 == strcmp (proxy_type, "SOCKS4A"))
2293  plugin->proxytype = CURLPROXY_SOCKS4A;
2294  else if (0 == strcmp (proxy_type, "SOCKS5_HOSTNAME "))
2295  plugin->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
2296  else
2297  {
2299  _ (
2300  "Invalid proxy type: `%s', disabling proxy! Check configuration!\n"),
2301  proxy_type);
2302 
2303  GNUNET_free (proxy_type);
2304  GNUNET_free (plugin->proxy_hostname);
2305  plugin->proxy_hostname = NULL;
2306  GNUNET_free (plugin->proxy_username);
2307  plugin->proxy_username = NULL;
2308  GNUNET_free (plugin->proxy_password);
2309  plugin->proxy_password = NULL;
2310 
2311  return GNUNET_SYSERR;
2312  }
2313 
2315  "Found proxy type: `%s'\n",
2316  proxy_type);
2317  }
2318 
2319  /* proxy http tunneling */
2322  plugin->name,
2323  "PROXY_HTTP_TUNNELING");
2326 
2327  GNUNET_free (proxy_type);
2328  }
2329 
2330  /* Should we emulate an XHR client for testing? */
2331  plugin->emulate_xhr
2333  plugin->name,
2334  "EMULATE_XHR");
2335  return GNUNET_OK;
2336 }
2337 
2338 
2347 static const char *
2349  const void *addr,
2350  size_t addrlen)
2351 {
2353  addr,
2354  addrlen);
2355 }
2356 
2357 
2367 static void
2369  const struct
2371  struct GNUNET_ATS_Session *session)
2372 {
2374 }
2375 
2376 
2387 static void
2389  const struct GNUNET_PeerIdentity *peer,
2390  struct GNUNET_ATS_Session *s,
2391  struct GNUNET_TIME_Relative delay)
2392 {
2395  "New inbound delay %s\n",
2397  GNUNET_NO));
2398  if (s->recv_wakeup_task != NULL)
2399  {
2401  s->recv_wakeup_task
2403  &client_wake_up,
2404  s);
2405  }
2406 }
2407 
2408 
2418 static int
2420  const struct GNUNET_PeerIdentity *peer,
2421  void *value)
2422 {
2423  struct HTTP_Client_Plugin *plugin = cls;
2424  struct GNUNET_ATS_Session *session = value;
2425 
2426  notify_session_monitor (plugin,
2427  session,
2429  notify_session_monitor (plugin,
2430  session,
2431  GNUNET_TRANSPORT_SS_UP); /* FIXME: or handshake? */
2432  return GNUNET_OK;
2433 }
2434 
2435 
2448 static void
2451  void *sic_cls)
2452 {
2453  struct HTTP_Client_Plugin *plugin = cls;
2454 
2455  plugin->sic = sic;
2456  plugin->sic_cls = sic_cls;
2457  if (NULL != sic)
2458  {
2461  plugin);
2462  /* signal end of first iteration */
2463  sic (sic_cls, NULL, NULL);
2464  }
2465 }
2466 
2467 
2471 void *
2473 {
2476  struct HTTP_Client_Plugin *plugin;
2477 
2478  if (NULL == env->receive)
2479  {
2480  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
2481  initialze the plugin or the API */
2483  api->cls = NULL;
2487  return api;
2488  }
2489 
2490  plugin = GNUNET_new (struct HTTP_Client_Plugin);
2491  plugin->env = env;
2493  GNUNET_YES);
2495  api->cls = plugin;
2496  api->send = &http_client_plugin_send;
2510 #if BUILD_HTTPS
2511  plugin->name = "transport-https_client";
2512  plugin->protocol = "https";
2513 #else
2514  plugin->name = "transport-http_client";
2515  plugin->protocol = "http";
2516 #endif
2517  plugin->last_tag = 1;
2518 
2519  if (GNUNET_SYSERR == client_configure_plugin (plugin))
2520  {
2522  return NULL;
2523  }
2524 
2525  /* Start client */
2526  if (GNUNET_SYSERR == client_start (plugin))
2527  {
2529  return NULL;
2530  }
2531  return api;
2532 }
2533 
2534 
2535 /* 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.
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, WANT 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:246
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.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static curl_proxytype proxy_type
Proxy type we are using (can be NULL).
const struct GNUNET_PeerIdentity * my_identity
Identity of this peer.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static void client_session_timeout(void *cls)
Session was idle, so disconnect it.
enum GNUNET_GenericReturnValue 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_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...
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#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).
enum GNUNET_GenericReturnValue 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.
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:1117
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:184
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:1263
const struct GNUNET_HELLO_Address * address
Address we are looking for.
Information about a plugin&#39;s session.
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:1269
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1247
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:593
void * cls
Closure for the various callbacks.
enum State state
current state of profiling
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)...
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
Temporarily disconnected.
#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:411
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.
Session handle for connections.
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:1296
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:93
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:702
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:1841
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:85
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:442
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:114
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.
#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
static char * plugin
Solver plugin name as string.
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 int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
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 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:124
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.
enum GNUNET_GenericReturnValue 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".
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.
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:354
#define LOG(kind,...)
enum HTTP_PUT_REQUEST_STATE state
Current state of this request.
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.
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:972