GNUnet  0.19.5
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 
241 
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 {
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);
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 
560 static void
561 client_run (void *cls);
562 
563 
571 static int
573  int now)
574 {
575  fd_set rs;
576  fd_set ws;
577  fd_set es;
578  int max;
579  struct GNUNET_NETWORK_FDSet *grs;
580  struct GNUNET_NETWORK_FDSet *gws;
581  long to;
582  CURLMcode mret;
584 
585  /* Cancel previous scheduled task */
586  if (plugin->client_perform_task != NULL)
587  {
588  GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
589  plugin->client_perform_task = NULL;
590  }
591  max = -1;
592  FD_ZERO (&rs);
593  FD_ZERO (&ws);
594  FD_ZERO (&es);
595  mret = curl_multi_fdset (plugin->curl_multi_handle, &rs, &ws, &es, &max);
596  if (mret != CURLM_OK)
597  {
599  _ ("%s failed at %s:%d: `%s'\n"),
600  "curl_multi_fdset",
601  __FILE__,
602  __LINE__,
603  curl_multi_strerror (mret));
604  return GNUNET_SYSERR;
605  }
606  mret = curl_multi_timeout (plugin->curl_multi_handle, &to);
607  if (-1 == to)
609  else
611  if (now == GNUNET_YES)
613 
614  if (CURLM_OK != mret)
615  {
617  _ ("%s failed at %s:%d: `%s'\n"),
618  "curl_multi_timeout", __FILE__, __LINE__,
619  curl_multi_strerror (mret));
620  return GNUNET_SYSERR;
621  }
622 
625  GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
626  GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
627 
628  /* Schedule task to run when select is ready to read or write */
629  plugin->client_perform_task =
631  timeout, grs, gws,
632  &client_run, plugin);
635  return GNUNET_OK;
636 }
637 
638 
639 #if VERBOSE_CURL
650 static int
651 client_log (CURL *curl,
652  curl_infotype type,
653  const char *data,
654  size_t size,
655  void *cls)
656 {
657  struct RequestHandle *ch = cls;
658  const char *ttype = "UNSPECIFIED";
659  char text[size + 2];
660 
661  if (! ((CURLINFO_TEXT == type) ||
662  (CURLINFO_HEADER_IN == type) ||
663  (CURLINFO_HEADER_OUT == type)))
664  return 0;
665  switch (type)
666  {
667  case CURLINFO_TEXT:
668  ttype = "TEXT";
669  break;
670 
671  case CURLINFO_HEADER_IN:
672  ttype = "HEADER_IN";
673  break;
674 
675  case CURLINFO_HEADER_OUT:
676  ttype = "HEADER_OUT";
677  /* Overhead*/
678  GNUNET_assert (NULL != ch);
679  GNUNET_assert (NULL != ch->easyhandle);
680  GNUNET_assert (NULL != ch->s);
681  ch->s->overhead += size;
682  break;
683 
684  default:
685  ttype = "UNSPECIFIED";
686  break;
687  }
688  GNUNET_memcpy (text, data, size);
689  if (text[size - 1] == '\n')
690  {
691  text[size] = '\0';
692  }
693  else
694  {
695  text[size] = '\n';
696  text[size + 1] = '\0';
697  }
699  "Request %p %s: %s",
700  ch->easyhandle,
701  ttype,
702  text);
703  return 0;
704 }
705 
706 
707 #endif
708 
715 static int
717 
718 
725 static int
727 
728 
756 static ssize_t
758  struct GNUNET_ATS_Session *s,
759  const char *msgbuf,
760  size_t msgbuf_size,
761  unsigned int priority,
762  struct GNUNET_TIME_Relative to,
764  void *cont_cls)
765 {
766  struct HTTP_Client_Plugin *plugin = cls;
767  struct HTTP_Message *msg;
768  char *stat_txt;
769 
771  "Session %p/request %p: Sending message with %lu to peer `%s' \n",
772  s,
773  s->put.easyhandle,
774  (unsigned long) msgbuf_size,
775  GNUNET_i2s (&s->address->peer));
776 
777  /* create new message and schedule */
778  msg = GNUNET_malloc (sizeof(struct HTTP_Message) + msgbuf_size);
779  msg->size = msgbuf_size;
780  msg->buf = (char *) &msg[1];
781  msg->transmit_cont = cont;
782  msg->transmit_cont_cls = cont_cls;
783  GNUNET_memcpy (msg->buf,
784  msgbuf,
785  msgbuf_size);
787  s->msg_tail,
788  msg);
789  s->msgs_in_queue++;
790  s->bytes_in_queue += msg->size;
791 
792  GNUNET_asprintf (&stat_txt,
793  "# bytes currently in %s_client buffers",
794  plugin->protocol);
795  GNUNET_STATISTICS_update (plugin->env->stats,
796  stat_txt, msgbuf_size, GNUNET_NO);
797  GNUNET_free (stat_txt);
799  s,
801  if (H_TMP_DISCONNECTING == s->put.state)
802  {
803  /* PUT request is currently getting disconnected */
806  "Session %p/request %p: currently disconnecting, reconnecting immediately\n",
807  s,
808  s->put.easyhandle);
809  return msgbuf_size;
810  }
811  if (H_PAUSED == s->put.state)
812  {
813  /* PUT request was paused, unpause */
814  GNUNET_assert (s->put_disconnect_task != NULL);
816  s->put_disconnect_task = NULL;
818  "Session %p/request %p: unpausing request\n",
819  s, s->put.easyhandle);
820  s->put.state = H_CONNECTED;
821  if (NULL != s->put.easyhandle)
822  curl_easy_pause (s->put.easyhandle, CURLPAUSE_CONT);
823  }
824  else if (H_TMP_DISCONNECTED == s->put.state)
825  {
826  /* PUT request was disconnected, reconnect */
827  LOG (GNUNET_ERROR_TYPE_DEBUG, "Session %p: Reconnecting PUT request\n", s);
828  GNUNET_break (NULL == s->put.easyhandle);
830  {
831  /* Could not reconnect */
833  return GNUNET_SYSERR;
834  }
835  }
837  return msgbuf_size;
838 }
839 
840 
848 static int
850  struct GNUNET_ATS_Session *s)
851 {
852  struct HTTP_Client_Plugin *plugin = cls;
853 
855  "Session %p: notifying transport about ending session\n",
856  s);
857  plugin->env->session_end (plugin->env->cls,
858  s->address,
859  s);
861 
862  /* Re-schedule since handles have changed */
863  if (NULL != plugin->client_perform_task)
864  {
865  GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
866  plugin->client_perform_task = NULL;
867  }
869 
870  return GNUNET_OK;
871 }
872 
873 
882 static unsigned int
884 {
885  return 3;
886 }
887 
888 
897 static int
899  const struct GNUNET_PeerIdentity *peer,
900  void *value)
901 {
902  struct HTTP_Client_Plugin *plugin = cls;
903  struct GNUNET_ATS_Session *session = value;
904 
906  return GNUNET_OK;
907 }
908 
909 
918 static void
920  const struct GNUNET_PeerIdentity *target)
921 {
922  struct HTTP_Client_Plugin *plugin = cls;
923 
925  "Transport tells me to disconnect `%s'\n",
926  GNUNET_i2s (target));
928  target,
930  plugin);
931 }
932 
933 
938 {
943 
948 };
949 
950 
959 static int
961  const struct GNUNET_PeerIdentity *key,
962  void *value)
963 {
964  struct GNUNET_ATS_SessionClientCtx *sc_ctx = cls;
965  struct GNUNET_ATS_Session *s = value;
966 
967  if (0 == GNUNET_HELLO_address_cmp (sc_ctx->address,
968  s->address))
969  {
970  sc_ctx->ret = s;
971  return GNUNET_NO;
972  }
973  return GNUNET_YES;
974 }
975 
976 
984 static struct GNUNET_ATS_Session *
986  const struct GNUNET_HELLO_Address *address)
987 {
988  struct GNUNET_ATS_SessionClientCtx sc_ctx;
989 
990  sc_ctx.address = address;
991  sc_ctx.ret = NULL;
994  &sc_ctx);
995  return sc_ctx.ret;
996 }
997 
998 
1006 static void
1008 {
1009  struct GNUNET_ATS_Session *s = cls;
1010 
1011  s->put_disconnect_task = NULL;
1013  "Session %p/request %p: will be disconnected due to no activity\n",
1014  s, s->put.easyhandle);
1016  if (NULL != s->put.easyhandle)
1017  curl_easy_pause (s->put.easyhandle,
1018  CURLPAUSE_CONT);
1020 }
1021 
1022 
1033 static size_t
1034 client_send_cb (void *stream,
1035  size_t size,
1036  size_t nmemb,
1037  void *cls)
1038 {
1039  struct GNUNET_ATS_Session *s = cls;
1040  struct HTTP_Client_Plugin *plugin = s->plugin;
1041  struct HTTP_Message *msg = s->msg_head;
1042  size_t len;
1043  char *stat_txt;
1044 
1045  if (H_TMP_DISCONNECTING == s->put.state)
1046  {
1048  "Session %p/request %p: disconnect due to inactivity\n",
1049  s, s->put.easyhandle);
1050  return 0;
1051  }
1052 
1053  if (NULL == msg)
1054  {
1055  if (GNUNET_YES == plugin->emulate_xhr)
1056  {
1058  "Session %p/request %p: PUT request finished\n",
1059  s,
1060  s->put.easyhandle);
1062  return 0;
1063  }
1064 
1065  /* We have nothing to send, so pause PUT request */
1067  "Session %p/request %p: nothing to send, suspending\n",
1068  s,
1069  s->put.easyhandle);
1073  s);
1074  s->put.state = H_PAUSED;
1075  return CURL_READFUNC_PAUSE;
1076  }
1077  /* data to send */
1078  GNUNET_assert (msg->pos < msg->size);
1079  /* calculate how much fits in buffer */
1080  len = GNUNET_MIN (msg->size - msg->pos,
1081  size * nmemb);
1082  GNUNET_memcpy (stream,
1083  &msg->buf[msg->pos],
1084  len);
1085  msg->pos += len;
1086  if (msg->pos == msg->size)
1087  {
1089  "Session %p/request %p: sent message with %lu bytes sent, removing message from queue\n",
1090  s,
1091  s->put.easyhandle,
1092  (unsigned long) msg->size);
1093  /* Calling transmit continuation */
1095  s->msg_tail,
1096  msg);
1097  GNUNET_assert (0 < s->msgs_in_queue);
1098  s->msgs_in_queue--;
1100  s->bytes_in_queue -= msg->size;
1101  if (NULL != msg->transmit_cont)
1102  msg->transmit_cont (msg->transmit_cont_cls,
1103  &s->address->peer,
1104  GNUNET_OK,
1105  msg->size,
1106  msg->size + s->overhead);
1107  s->overhead = 0;
1108  GNUNET_free (msg);
1109  }
1111  s,
1113  GNUNET_asprintf (&stat_txt,
1114  "# bytes currently in %s_client buffers",
1115  plugin->protocol);
1116  GNUNET_STATISTICS_update (plugin->env->stats,
1117  stat_txt,
1118  -len,
1119  GNUNET_NO);
1120  GNUNET_free (stat_txt);
1121  GNUNET_asprintf (&stat_txt,
1122  "# bytes transmitted via %s_client",
1123  plugin->protocol);
1124  GNUNET_STATISTICS_update (plugin->env->stats,
1125  stat_txt,
1126  len,
1127  GNUNET_NO);
1128  GNUNET_free (stat_txt);
1129  return len;
1130 }
1131 
1132 
1138 static void
1139 client_wake_up (void *cls)
1140 {
1141  struct GNUNET_ATS_Session *s = cls;
1142 
1143  s->recv_wakeup_task = NULL;
1145  "Session %p/request %p: Waking up GET handle\n",
1146  s, s->get.easyhandle);
1147  if (H_PAUSED == s->put.state)
1148  {
1149  /* PUT request was paused, unpause */
1150  GNUNET_assert (s->put_disconnect_task != NULL);
1152  s->put_disconnect_task = NULL;
1153  s->put.state = H_CONNECTED;
1154  if (NULL != s->put.easyhandle)
1155  curl_easy_pause (s->put.easyhandle, CURLPAUSE_CONT);
1156  }
1157  if (NULL != s->get.easyhandle)
1158  curl_easy_pause (s->get.easyhandle, CURLPAUSE_CONT);
1159 }
1160 
1161 
1169 static int
1171  const struct GNUNET_MessageHeader *message)
1172 {
1173  struct GNUNET_ATS_Session *s = cls;
1174  struct HTTP_Client_Plugin *plugin;
1175  struct GNUNET_TIME_Relative delay;
1176  char *stat_txt;
1177 
1178  plugin = s->plugin;
1179  delay = s->plugin->env->receive (plugin->env->cls,
1180  s->address,
1181  s,
1182  message);
1183  GNUNET_asprintf (&stat_txt,
1184  "# bytes received via %s_client",
1185  plugin->protocol);
1186  GNUNET_STATISTICS_update (plugin->env->stats,
1187  stat_txt,
1188  ntohs (message->size),
1189  GNUNET_NO);
1190  GNUNET_free (stat_txt);
1191 
1193  if (GNUNET_TIME_absolute_get ().abs_value_us < s->next_receive.abs_value_us)
1194  {
1196  "Client: peer `%s' address `%s' next read delayed for %s\n",
1197  GNUNET_i2s (&s->address->peer),
1199  s->address->address,
1200  s->address->address_length),
1202  GNUNET_YES));
1203  }
1205  return GNUNET_OK;
1206 }
1207 
1208 
1219 static size_t
1220 client_receive_put (void *stream,
1221  size_t size,
1222  size_t nmemb,
1223  void *cls)
1224 {
1225  return size * nmemb;
1226 }
1227 
1228 
1239 static size_t
1240 client_receive (void *stream,
1241  size_t size,
1242  size_t nmemb,
1243  void *cls)
1244 {
1245  struct GNUNET_ATS_Session *s = cls;
1246  struct GNUNET_TIME_Absolute now;
1247  size_t len = size * nmemb;
1248 
1250  "Session %p / request %p: Received %lu bytes from peer `%s'\n",
1251  s,
1252  s->get.easyhandle,
1253  (unsigned long) len,
1254  GNUNET_i2s (&s->address->peer));
1255  now = GNUNET_TIME_absolute_get ();
1256  if (now.abs_value_us < s->next_receive.abs_value_us)
1257  {
1261 
1263  "Session %p / request %p: No inbound bandwidth available! Next read was delayed for %s\n",
1264  s,
1265  s->get.easyhandle,
1267  GNUNET_YES));
1268  if (s->recv_wakeup_task != NULL)
1269  {
1271  s->recv_wakeup_task = NULL;
1272  }
1273  s->recv_wakeup_task
1275  &client_wake_up,
1276  s);
1277  return CURL_WRITEFUNC_PAUSE;
1278  }
1279  if (NULL == s->msg_tk)
1281  s);
1283  stream,
1284  len,
1285  GNUNET_NO,
1286  GNUNET_NO);
1287  return len;
1288 }
1289 
1290 
1291 static void
1292 client_run (void *cls)
1293 {
1294  struct HTTP_Client_Plugin *plugin = cls;
1295  int running;
1296  long http_statuscode;
1297  CURLMcode mret;
1298  CURLMsg *msg;
1299  int put_request; /* GNUNET_YES if easy handle is put, GNUNET_NO for get */
1300  int msgs_left;
1301 
1302  plugin->client_perform_task = NULL;
1303  /* While data are available or timeouts occurred */
1304  do
1305  {
1306  running = 0;
1307  /* Perform operations for all handles */
1308  mret = curl_multi_perform (plugin->curl_multi_handle, &running);
1309 
1310  /* Get additional information for all handles */
1311  while (NULL != (msg = curl_multi_info_read (plugin->curl_multi_handle,
1312  &msgs_left)))
1313  {
1314  CURL *easy_h = msg->easy_handle;
1315  struct GNUNET_ATS_Session *s = NULL;
1316  char *d = NULL; /* curl requires 'd' to be a 'char *' */
1317 
1318  GNUNET_assert (NULL != easy_h);
1319 
1320  /* Obtain session from easy handle */
1321  GNUNET_assert (CURLE_OK == curl_easy_getinfo (easy_h, CURLINFO_PRIVATE,
1322  &d));
1323  s = (struct GNUNET_ATS_Session *) d;
1324  GNUNET_assert (NULL != s);
1325 
1326  if (msg->msg != CURLMSG_DONE)
1327  continue; /* This should not happen */
1328 
1329  /* Get HTTP response code */
1330  GNUNET_break (CURLE_OK == curl_easy_getinfo (easy_h,
1331  CURLINFO_RESPONSE_CODE,
1332  &http_statuscode));
1333 
1334  if (easy_h == s->put.easyhandle)
1335  put_request = GNUNET_YES;
1336  else
1337  put_request = GNUNET_NO;
1338 
1339  /* Log status of terminated request */
1340  if ((0 != msg->data.result) || (http_statuscode != 200))
1342  "Session %p/request %p: %s request to `%s' ended with status %li reason %i: `%s'\n",
1343  s, msg->easy_handle,
1344  (GNUNET_YES == put_request) ? "PUT" : "GET",
1345  GNUNET_i2s (&s->address->peer),
1346  http_statuscode,
1347  msg->data.result,
1348  curl_easy_strerror (msg->data.result));
1349  else
1351  "Session %p/request %p: %s request to `%s' ended normal\n",
1352  s, msg->easy_handle,
1353  (GNUNET_YES == put_request) ? "PUT" : "GET",
1354  GNUNET_i2s (&s->address->peer));
1355 
1356  /* Remove easy handle from multi handle */
1357  curl_multi_remove_handle (plugin->curl_multi_handle, easy_h);
1358 
1359  /* Clean up easy handle */
1360  curl_easy_cleanup (easy_h);
1361 
1362  /* Remove information */
1363  GNUNET_assert (plugin->cur_requests > 0);
1364  plugin->cur_requests--;
1366  "%s request to %s done, number of requests decreased to %u\n",
1367  (GNUNET_YES == put_request) ? "PUT" : "GET",
1368  s->url,
1369  plugin->cur_requests);
1370 
1371  if (GNUNET_YES == put_request)
1372  {
1373  /* Clean up a PUT request */
1374  s->put.easyhandle = NULL;
1375  s->put.s = NULL;
1376 
1377  switch (s->put.state)
1378  {
1379  case H_NOT_CONNECTED:
1380  case H_DISCONNECTED:
1381  case H_TMP_DISCONNECTED:
1382  /* This must not happen */
1383  GNUNET_break (0);
1384  break;
1385 
1387  /* Transport called send while disconnect in progress, reconnect */
1388  if (GNUNET_SYSERR == client_connect_put (s))
1389  {
1390  /* Reconnect failed, disconnect session */
1392  }
1393  break;
1394 
1395  case H_TMP_DISCONNECTING:
1396  /* PUT gets temporarily disconnected */
1398  break;
1399 
1400  case H_PAUSED:
1401  case H_CONNECTED:
1402  /* PUT gets permanently disconnected */
1403  s->put.state = H_DISCONNECTED;
1405  break;
1406 
1407  default:
1408  GNUNET_break (0);
1409  break;
1410  }
1411  }
1412  else if (GNUNET_NO == put_request)
1413  {
1414  /* Clean up a GET request */
1415  s->get.easyhandle = NULL;
1416  s->get.s = NULL;
1417 
1418  /* If we are emulating an XHR client we need to make another GET
1419  * request.
1420  */
1421  if (GNUNET_YES == plugin->emulate_xhr)
1422  {
1423  if (GNUNET_SYSERR == client_connect_get (s))
1425  }
1426  else
1427  {
1428  /* GET request was terminated, so disconnect session */
1430  }
1431  }
1432  else
1433  GNUNET_break (0); /* Must not happen */
1434 
1435  GNUNET_STATISTICS_set (plugin->env->stats,
1437  plugin->cur_requests,
1438  GNUNET_NO);
1439  }
1440  }
1441  while (mret == CURLM_CALL_MULTI_PERFORM);
1443 }
1444 
1445 
1446 #ifdef TCP_STEALTH
1455 static curl_socket_t
1456 open_tcp_stealth_socket_cb (void *clientp,
1457  curlsocktype purpose,
1458  struct curl_sockaddr *address)
1459 {
1460  struct GNUNET_ATS_Session *s = clientp;
1461  int ret;
1462 
1463  switch (purpose)
1464  {
1465  case CURLSOCKTYPE_IPCXN:
1466  ret = socket (address->family,
1467  address->socktype,
1468  address->protocol);
1469  if (-1 == ret)
1470  return CURL_SOCKET_BAD;
1471  if (((SOCK_STREAM != address->socktype) ||
1472  ((0 != address->protocol) &&
1473  (IPPROTO_TCP != address->protocol))))
1474  return (curl_socket_t) ret;
1475  if ((0 != setsockopt (ret,
1476  IPPROTO_TCP,
1477  TCP_STEALTH,
1478  &s->address->peer,
1479  sizeof(struct GNUNET_PeerIdentity))))
1480  {
1482  _ ("TCP_STEALTH not supported on this platform.\n"));
1483  (void) close (ret);
1484  return CURL_SOCKET_BAD;
1485  }
1486  return (curl_socket_t) ret;
1487 
1488  case CURLSOCKTYPE_ACCEPT:
1489  GNUNET_break (0);
1490  return CURL_SOCKET_BAD;
1491  break;
1492 
1493  case CURLSOCKTYPE_LAST:
1494  GNUNET_break (0);
1495  return CURL_SOCKET_BAD;
1496 
1497  default:
1498  GNUNET_break (0);
1499  return CURL_SOCKET_BAD;
1500  }
1501 }
1502 
1503 
1504 #endif
1505 
1506 
1513 static int
1515 {
1516  CURLMcode mret;
1517  struct HttpAddress *ha;
1518  uint32_t options;
1519 
1520  ha = (struct HttpAddress *) s->address->address;
1521  options = ntohl (ha->options);
1522  /* create get request */
1523  s->get.easyhandle = curl_easy_init ();
1524  s->get.s = s;
1525  if (0 != (options & HTTP_OPTIONS_TCP_STEALTH))
1526  {
1527 #ifdef TCP_STEALTH
1528  curl_easy_setopt (s->get.easyhandle,
1529  CURLOPT_OPENSOCKETFUNCTION,
1530  &open_tcp_stealth_socket_cb);
1531  curl_easy_setopt (s->get.easyhandle,
1532  CURLOPT_OPENSOCKETDATA,
1533  s);
1534 #else
1536  "Cannot connect, TCP STEALTH needed and not supported by kernel.\n");
1537  curl_easy_cleanup (s->get.easyhandle);
1538  s->get.easyhandle = NULL;
1539  s->get.s = NULL;
1540  return GNUNET_SYSERR;
1541 #endif
1542  }
1543 
1544 #if VERBOSE_CURL
1545  curl_easy_setopt (s->get.easyhandle,
1546  CURLOPT_VERBOSE,
1547  1L);
1548  curl_easy_setopt (s->get.easyhandle,
1549  CURLOPT_DEBUGFUNCTION,
1550  &client_log);
1551  curl_easy_setopt (s->get.easyhandle,
1552  CURLOPT_DEBUGDATA,
1553  &s->get);
1554 #endif
1555 #if BUILD_HTTPS
1556  curl_easy_setopt (s->get.easyhandle, CURLOPT_SSLVERSION,
1557  CURL_SSLVERSION_TLSv1);
1558  {
1561  {
1562  curl_easy_setopt (s->get.easyhandle,
1563  CURLOPT_SSL_VERIFYPEER, 1L);
1564  curl_easy_setopt (s->get.easyhandle,
1565  CURLOPT_SSL_VERIFYHOST,
1566  2L);
1567  }
1568  else
1569  {
1570  curl_easy_setopt (s->get.easyhandle,
1571  CURLOPT_SSL_VERIFYPEER,
1572  0L);
1573  curl_easy_setopt (s->get.easyhandle,
1574  CURLOPT_SSL_VERIFYHOST,
1575  0L);
1576  }
1577  }
1578  curl_easy_setopt (s->get.easyhandle,
1579  CURLOPT_PROTOCOLS,
1580  CURLPROTO_HTTPS);
1581  curl_easy_setopt (s->get.easyhandle,
1582  CURLOPT_REDIR_PROTOCOLS,
1583  CURLPROTO_HTTPS);
1584 #else
1585  curl_easy_setopt (s->get.easyhandle,
1586  CURLOPT_PROTOCOLS,
1587  CURLPROTO_HTTP);
1588  curl_easy_setopt (s->get.easyhandle,
1589  CURLOPT_REDIR_PROTOCOLS,
1590  CURLPROTO_HTTP);
1591 #endif
1592 
1593  if (NULL != s->plugin->proxy_hostname)
1594  {
1595  curl_easy_setopt (s->get.easyhandle,
1596  CURLOPT_PROXY,
1597  s->plugin->proxy_hostname);
1598  curl_easy_setopt (s->get.easyhandle,
1599  CURLOPT_PROXYTYPE,
1600  s->plugin->proxytype);
1601  if (NULL != s->plugin->proxy_username)
1602  curl_easy_setopt (s->get.easyhandle,
1603  CURLOPT_PROXYUSERNAME,
1604  s->plugin->proxy_username);
1605  if (NULL != s->plugin->proxy_password)
1606  curl_easy_setopt (s->get.easyhandle,
1607  CURLOPT_PROXYPASSWORD,
1608  s->plugin->proxy_password);
1609  if (GNUNET_YES == s->plugin->proxy_use_httpproxytunnel)
1610  curl_easy_setopt (s->get.easyhandle,
1611  CURLOPT_HTTPPROXYTUNNEL,
1612  s->plugin->proxy_use_httpproxytunnel);
1613  }
1614 
1615  if (GNUNET_YES == s->plugin->emulate_xhr)
1616  {
1617  char *url;
1618 
1619  GNUNET_asprintf (&url,
1620  "%s,1",
1621  s->url);
1622  curl_easy_setopt (s->get.easyhandle,
1623  CURLOPT_URL,
1624  url);
1625  GNUNET_free (url);
1626  }
1627  else
1628  {
1629  curl_easy_setopt (s->get.easyhandle,
1630  CURLOPT_URL,
1631  s->url);
1632  }
1633  curl_easy_setopt (s->get.easyhandle,
1634  CURLOPT_READFUNCTION,
1635  &client_send_cb);
1636  curl_easy_setopt (s->get.easyhandle,
1637  CURLOPT_READDATA,
1638  s);
1639  curl_easy_setopt (s->get.easyhandle,
1640  CURLOPT_WRITEFUNCTION,
1641  &client_receive);
1642  curl_easy_setopt (s->get.easyhandle,
1643  CURLOPT_WRITEDATA,
1644  s);
1645  /* No timeout by default, timeout done with session timeout */
1646  curl_easy_setopt (s->get.easyhandle,
1647  CURLOPT_TIMEOUT,
1648  0L);
1649  curl_easy_setopt (s->get.easyhandle,
1650  CURLOPT_PRIVATE, s);
1651  curl_easy_setopt (s->get.easyhandle,
1652  CURLOPT_CONNECTTIMEOUT_MS,
1653  (long) (HTTP_CLIENT_NOT_VALIDATED_TIMEOUT.rel_value_us
1654  / 1000LL));
1655  curl_easy_setopt (s->get.easyhandle, CURLOPT_BUFFERSIZE,
1657 #if CURL_TCP_NODELAY
1658  curl_easy_setopt (ps->recv_endpoint,
1659  CURLOPT_TCP_NODELAY,
1660  1L);
1661 #endif
1662  curl_easy_setopt (s->get.easyhandle,
1663  CURLOPT_FOLLOWLOCATION,
1664  0L);
1665 
1666  mret = curl_multi_add_handle (s->plugin->curl_multi_handle,
1667  s->get.easyhandle);
1668  if (CURLM_OK != mret)
1669  {
1671  "Session %p : Failed to add GET handle to multihandle: `%s'\n",
1672  s,
1673  curl_multi_strerror (mret));
1674  curl_easy_cleanup (s->get.easyhandle);
1675  s->get.easyhandle = NULL;
1676  s->get.s = NULL;
1677  GNUNET_break (0);
1678  return GNUNET_SYSERR;
1679  }
1680  s->plugin->cur_requests++;
1682  "GET request `%s' established, number of requests increased to %u\n",
1683  s->url,
1684  s->plugin->cur_requests);
1685  return GNUNET_OK;
1686 }
1687 
1688 
1689 static int
1691 {
1692  CURLMcode mret;
1693  struct HttpAddress *ha;
1694  uint32_t options;
1695 
1696  ha = (struct HttpAddress *) s->address->address;
1697  options = ntohl (ha->options);
1698  /* create put request */
1700  "Session %p: Init PUT handle\n",
1701  s);
1702  s->put.easyhandle = curl_easy_init ();
1703  s->put.s = s;
1704 #if VERBOSE_CURL
1705  curl_easy_setopt (s->put.easyhandle,
1706  CURLOPT_VERBOSE,
1707  1L);
1708  curl_easy_setopt (s->put.easyhandle,
1709  CURLOPT_DEBUGFUNCTION,
1710  &client_log);
1711  curl_easy_setopt (s->put.easyhandle,
1712  CURLOPT_DEBUGDATA,
1713  &s->put);
1714 #endif
1715  if (0 != (options & HTTP_OPTIONS_TCP_STEALTH))
1716  {
1717 #ifdef TCP_STEALTH
1718  curl_easy_setopt (s->put.easyhandle,
1719  CURLOPT_OPENSOCKETFUNCTION,
1720  &open_tcp_stealth_socket_cb);
1721  curl_easy_setopt (s->put.easyhandle,
1722  CURLOPT_OPENSOCKETDATA,
1723  s);
1724 #else
1726  "Cannot connect, TCP STEALTH needed and not supported by kernel.\n");
1727  curl_easy_cleanup (s->put.easyhandle);
1728  s->put.easyhandle = NULL;
1729  s->put.s = NULL;
1730  s->put.state = H_DISCONNECTED;
1731  return GNUNET_SYSERR;
1732 #endif
1733  }
1734 #if BUILD_HTTPS
1735  curl_easy_setopt (s->put.easyhandle,
1736  CURLOPT_SSLVERSION,
1737  CURL_SSLVERSION_TLSv1);
1738  {
1739  struct HttpAddress *ha;
1740  ha = (struct HttpAddress *) s->address->address;
1741 
1743  (ntohl (ha->options) & HTTP_OPTIONS_VERIFY_CERTIFICATE))
1744  {
1745  curl_easy_setopt (s->put.easyhandle,
1746  CURLOPT_SSL_VERIFYPEER,
1747  1L);
1748  curl_easy_setopt (s->put.easyhandle,
1749  CURLOPT_SSL_VERIFYHOST,
1750  2L);
1751  }
1752  else
1753  {
1754  curl_easy_setopt (s->put.easyhandle,
1755  CURLOPT_SSL_VERIFYPEER,
1756  0L);
1757  curl_easy_setopt (s->put.easyhandle,
1758  CURLOPT_SSL_VERIFYHOST,
1759  0L);
1760  }
1761  }
1762  curl_easy_setopt (s->put.easyhandle,
1763  CURLOPT_PROTOCOLS,
1764  CURLPROTO_HTTPS);
1765  curl_easy_setopt (s->put.easyhandle,
1766  CURLOPT_REDIR_PROTOCOLS,
1767  CURLPROTO_HTTPS);
1768 #else
1769  curl_easy_setopt (s->put.easyhandle,
1770  CURLOPT_PROTOCOLS,
1771  CURLPROTO_HTTP);
1772  curl_easy_setopt (s->put.easyhandle,
1773  CURLOPT_REDIR_PROTOCOLS,
1774  CURLPROTO_HTTP);
1775 #endif
1776  if (NULL != s->plugin->proxy_hostname)
1777  {
1778  curl_easy_setopt (s->put.easyhandle,
1779  CURLOPT_PROXY,
1780  s->plugin->proxy_hostname);
1781  curl_easy_setopt (s->put.easyhandle,
1782  CURLOPT_PROXYTYPE,
1783  s->plugin->proxytype);
1784  if (NULL != s->plugin->proxy_username)
1785  curl_easy_setopt (s->put.easyhandle,
1786  CURLOPT_PROXYUSERNAME,
1787  s->plugin->proxy_username);
1788  if (NULL != s->plugin->proxy_password)
1789  curl_easy_setopt (s->put.easyhandle,
1790  CURLOPT_PROXYPASSWORD,
1791  s->plugin->proxy_password);
1792  if (GNUNET_YES == s->plugin->proxy_use_httpproxytunnel)
1793  curl_easy_setopt (s->put.easyhandle,
1794  CURLOPT_HTTPPROXYTUNNEL,
1795  s->plugin->proxy_use_httpproxytunnel);
1796  }
1797 
1798  curl_easy_setopt (s->put.easyhandle,
1799  CURLOPT_URL,
1800  s->url);
1801  curl_easy_setopt (s->put.easyhandle,
1802  CURLOPT_UPLOAD,
1803  1L);
1804  curl_easy_setopt (s->put.easyhandle,
1805  CURLOPT_READFUNCTION,
1806  &client_send_cb);
1807  curl_easy_setopt (s->put.easyhandle,
1808  CURLOPT_READDATA,
1809  s);
1810  curl_easy_setopt (s->put.easyhandle,
1811  CURLOPT_WRITEFUNCTION,
1813  curl_easy_setopt (s->put.easyhandle,
1814  CURLOPT_WRITEDATA,
1815  s);
1816  /* No timeout by default, timeout done with session timeout */
1817  curl_easy_setopt (s->put.easyhandle,
1818  CURLOPT_TIMEOUT,
1819  0L);
1820  curl_easy_setopt (s->put.easyhandle,
1821  CURLOPT_PRIVATE,
1822  s);
1823  curl_easy_setopt (s->put.easyhandle,
1824  CURLOPT_CONNECTTIMEOUT_MS,
1825  (long) (HTTP_CLIENT_NOT_VALIDATED_TIMEOUT.rel_value_us
1826  / 1000LL));
1827  curl_easy_setopt (s->put.easyhandle, CURLOPT_BUFFERSIZE,
1829 #if CURL_TCP_NODELAY
1830  curl_easy_setopt (s->put.easyhandle, CURLOPT_TCP_NODELAY, 1);
1831 #endif
1832  mret = curl_multi_add_handle (s->plugin->curl_multi_handle,
1833  s->put.easyhandle);
1834  if (CURLM_OK != mret)
1835  {
1837  "Session %p : Failed to add PUT handle to multihandle: `%s'\n",
1838  s, curl_multi_strerror (mret));
1839  curl_easy_cleanup (s->put.easyhandle);
1840  s->put.easyhandle = NULL;
1841  s->put.s = NULL;
1842  s->put.state = H_DISCONNECTED;
1843  return GNUNET_SYSERR;
1844  }
1845  s->put.state = H_CONNECTED;
1846  s->plugin->cur_requests++;
1847 
1849  "PUT request `%s' established, number of requests increased to %u\n",
1850  s->url, s->plugin->cur_requests);
1851 
1852  return GNUNET_OK;
1853 }
1854 
1855 
1862 static int
1864 {
1865  struct HTTP_Client_Plugin *plugin = s->plugin;
1866  int res = GNUNET_OK;
1867 
1868  /* create url */
1869  if (NULL ==
1871  s->address->address,
1872  s->address->address_length))
1873  {
1875  "Invalid address peer `%s'\n",
1876  GNUNET_i2s (&s->address->peer));
1877  return GNUNET_SYSERR;
1878  }
1879 
1880  GNUNET_asprintf (&s->url,
1881  "%s/%s;%u",
1883  s->address->address,
1884  s->address->address_length),
1885  GNUNET_i2s_full (plugin->env->my_identity),
1886  plugin->last_tag);
1887 
1888  plugin->last_tag++;
1890  "Initiating outbound session peer `%s' using address `%s'\n",
1891  GNUNET_i2s (&s->address->peer), s->url);
1892 
1893  if (GNUNET_SYSERR == client_connect_get (s))
1894  return GNUNET_SYSERR;
1895  /* If we are emulating an XHR client then delay sending a PUT request until
1896  * there is something to send.
1897  */
1898  if (GNUNET_YES == plugin->emulate_xhr)
1899  {
1901  }
1902  else if (GNUNET_SYSERR == client_connect_put (s))
1903  return GNUNET_SYSERR;
1904 
1906  "Session %p: connected with GET %p and PUT %p\n",
1907  s, s->get.easyhandle,
1908  s->put.easyhandle);
1909  /* Perform connect */
1910  GNUNET_STATISTICS_set (plugin->env->stats,
1912  plugin->cur_requests,
1913  GNUNET_NO);
1914  /* Re-schedule since handles have changed */
1915  if (NULL != plugin->client_perform_task)
1916  {
1917  GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
1918  plugin->client_perform_task = NULL;
1919  }
1920 
1921  /* Schedule task to run immediately */
1922  plugin->client_perform_task = GNUNET_SCHEDULER_add_now (client_run,
1923  plugin);
1924  return res;
1925 }
1926 
1927 
1935 static enum GNUNET_NetworkType
1937  struct GNUNET_ATS_Session *session)
1938 {
1939  return session->scope;
1940 }
1941 
1942 
1950 static enum GNUNET_NetworkType
1952  const struct
1954 {
1955  struct HTTP_Client_Plugin *plugin = cls;
1956 
1958  address);
1959 }
1960 
1961 
1967 static void
1969 {
1970  struct GNUNET_ATS_Session *s = cls;
1971  struct GNUNET_TIME_Relative left;
1972 
1973  s->timeout_task = NULL;
1975  if (0 != left.rel_value_us)
1976  {
1977  /* not actually our turn yet, but let's at least update
1978  the monitor, it may think we're about to die ... */
1980  s,
1984  s);
1985  return;
1986  }
1987  LOG (TIMEOUT_LOG,
1988  "Session %p was idle for %s, disconnecting\n",
1989  s,
1991  GNUNET_YES));
1994  s));
1995 }
1996 
1997 
2006 static struct GNUNET_ATS_Session *
2008  const struct GNUNET_HELLO_Address *address)
2009 {
2010  struct HTTP_Client_Plugin *plugin = cls;
2011  struct GNUNET_ATS_Session *s;
2012  struct sockaddr *sa;
2013  enum GNUNET_NetworkType net_type;
2014  size_t salen = 0;
2015  int res;
2016 
2017  GNUNET_assert (NULL != address->address);
2018 
2019  /* find existing session */
2021  if (NULL != s)
2022  return s;
2023 
2024  /* create a new session */
2025  if (plugin->max_requests <= plugin->cur_requests)
2026  {
2028  "Maximum number of requests (%u) reached: "
2029  "cannot connect to peer `%s'\n",
2030  plugin->max_requests,
2031  GNUNET_i2s (&address->peer));
2032  return NULL;
2033  }
2034 
2035  /* Determine network location */
2036  net_type = GNUNET_NT_UNSPECIFIED;
2038  address->address_length,
2039  &res);
2040  if (GNUNET_SYSERR == res)
2041  return NULL;
2042  if (GNUNET_YES == res)
2043  {
2044  GNUNET_assert (NULL != sa);
2045  if (AF_INET == sa->sa_family)
2046  {
2047  salen = sizeof(struct sockaddr_in);
2048  }
2049  else if (AF_INET6 == sa->sa_family)
2050  {
2051  salen = sizeof(struct sockaddr_in6);
2052  }
2053  net_type = plugin->env->get_address_type (plugin->env->cls, sa, salen);
2054  GNUNET_free (sa);
2055  }
2056  else if (GNUNET_NO == res)
2057  {
2058  /* Cannot convert to sockaddr -> is external hostname */
2059  net_type = GNUNET_NT_WAN;
2060  }
2061  if (GNUNET_NT_UNSPECIFIED == net_type)
2062  {
2063  GNUNET_break (0);
2064  return NULL;
2065  }
2066 
2067  s = GNUNET_new (struct GNUNET_ATS_Session);
2068  s->plugin = plugin;
2070  s->scope = net_type;
2071 
2072  s->put.state = H_NOT_CONNECTED;
2076  s);
2078  "Created new session %p for `%s' address `%s''\n",
2079  s,
2081  s->address->address,
2082  s->address->address_length),
2083  GNUNET_i2s (&s->address->peer));
2084 
2085  /* add new session */
2086  (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessions,
2087  &s->address->peer,
2088  s,
2090  /* initiate new connection */
2091  if (GNUNET_SYSERR == client_connect (s))
2092  {
2094  "Cannot connect to peer `%s' address `%s''\n",
2096  s->address->address,
2097  s->address->address_length),
2098  GNUNET_i2s (&s->address->peer));
2100  return NULL;
2101  }
2103  s,
2106  s,
2107  GNUNET_TRANSPORT_SS_UP); /* or handshake? */
2108  return s;
2109 }
2110 
2111 
2118 static int
2120 {
2121  curl_global_init (CURL_GLOBAL_ALL);
2122  plugin->curl_multi_handle = curl_multi_init ();
2123 
2124  if (NULL == plugin->curl_multi_handle)
2125  {
2127  _ (
2128  "Could not initialize curl multi handle, failed to start %s plugin!\n"),
2129  plugin->name);
2130  return GNUNET_SYSERR;
2131  }
2132  return GNUNET_OK;
2133 }
2134 
2135 
2148 static int
2150  const void *addr,
2151  size_t addrlen)
2152 {
2153  /* A HTTP/S client does not have any valid address so:*/
2154  return GNUNET_NO;
2155 }
2156 
2157 
2164 void *
2166 {
2167  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2168  struct HTTP_Client_Plugin *plugin = api->cls;
2169 
2170  if (NULL == api->cls)
2171  {
2172  /* Stub shutdown */
2173  GNUNET_free (api);
2174  return NULL;
2175  }
2177  _ ("Shutting down plugin `%s'\n"),
2178  plugin->name);
2181  plugin);
2182  if (NULL != plugin->client_perform_task)
2183  {
2184  GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
2185  plugin->client_perform_task = NULL;
2186  }
2187  if (NULL != plugin->curl_multi_handle)
2188  {
2189  curl_multi_cleanup (plugin->curl_multi_handle);
2190  plugin->curl_multi_handle = NULL;
2191  }
2192  curl_global_cleanup ();
2194  _ ("Shutdown for plugin `%s' complete\n"),
2195  plugin->name);
2197  GNUNET_free (plugin->proxy_hostname);
2198  GNUNET_free (plugin->proxy_username);
2199  GNUNET_free (plugin->proxy_password);
2200  GNUNET_free (plugin);
2201  GNUNET_free (api);
2202  return NULL;
2203 }
2204 
2205 
2212 static int
2214 {
2215  unsigned long long max_requests;
2216  char *proxy_type;
2217 
2218  /* Optional parameters */
2219  if (GNUNET_OK !=
2221  plugin->name,
2222  "MAX_CONNECTIONS",
2223  &max_requests))
2224  max_requests = 128;
2225  plugin->max_requests = max_requests;
2226 
2228  _ ("Maximum number of requests is %u\n"),
2229  plugin->max_requests);
2230 
2231  /* Read proxy configuration */
2232  if (GNUNET_OK ==
2234  plugin->name,
2235  "PROXY",
2236  &plugin->proxy_hostname))
2237  {
2239  "Found proxy host: `%s'\n",
2240  plugin->proxy_hostname);
2241  /* proxy username */
2242  if (GNUNET_OK ==
2244  plugin->name,
2245  "PROXY_USERNAME",
2246  &plugin->proxy_username))
2247  {
2249  "Found proxy username name: `%s'\n",
2250  plugin->proxy_username);
2251  }
2252 
2253  /* proxy password */
2254  if (GNUNET_OK ==
2256  plugin->name,
2257  "PROXY_PASSWORD",
2258  &plugin->proxy_password))
2259  {
2261  "Found proxy password name: `%s'\n",
2262  plugin->proxy_password);
2263  }
2264 
2265  /* proxy type */
2266  if (GNUNET_OK ==
2268  plugin->name,
2269  "PROXY_TYPE",
2270  &proxy_type))
2271  {
2273 
2274  if (0 == strcmp (proxy_type, "HTTP"))
2275  plugin->proxytype = CURLPROXY_HTTP;
2276  else if (0 == strcmp (proxy_type, "SOCKS4"))
2277  plugin->proxytype = CURLPROXY_SOCKS4;
2278  else if (0 == strcmp (proxy_type, "SOCKS5"))
2279  plugin->proxytype = CURLPROXY_SOCKS5;
2280  else if (0 == strcmp (proxy_type, "SOCKS4A"))
2281  plugin->proxytype = CURLPROXY_SOCKS4A;
2282  else if (0 == strcmp (proxy_type, "SOCKS5_HOSTNAME "))
2283  plugin->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
2284  else
2285  {
2287  _ (
2288  "Invalid proxy type: `%s', disabling proxy! Check configuration!\n"),
2289  proxy_type);
2290 
2292  GNUNET_free (plugin->proxy_hostname);
2293  plugin->proxy_hostname = NULL;
2294  GNUNET_free (plugin->proxy_username);
2295  plugin->proxy_username = NULL;
2296  GNUNET_free (plugin->proxy_password);
2297  plugin->proxy_password = NULL;
2298 
2299  return GNUNET_SYSERR;
2300  }
2301 
2303  "Found proxy type: `%s'\n",
2304  proxy_type);
2305  }
2306 
2307  /* proxy http tunneling */
2308  plugin->proxy_use_httpproxytunnel
2310  plugin->name,
2311  "PROXY_HTTP_TUNNELING");
2312  if (GNUNET_SYSERR == plugin->proxy_use_httpproxytunnel)
2313  plugin->proxy_use_httpproxytunnel = GNUNET_NO;
2314 
2316  }
2317 
2318  /* Should we emulate an XHR client for testing? */
2319  plugin->emulate_xhr
2321  plugin->name,
2322  "EMULATE_XHR");
2323  return GNUNET_OK;
2324 }
2325 
2326 
2335 static const char *
2337  const void *addr,
2338  size_t addrlen)
2339 {
2341  addr,
2342  addrlen);
2343 }
2344 
2345 
2355 static void
2357  const struct
2359  struct GNUNET_ATS_Session *session)
2360 {
2362 }
2363 
2364 
2375 static void
2377  const struct GNUNET_PeerIdentity *peer,
2378  struct GNUNET_ATS_Session *s,
2379  struct GNUNET_TIME_Relative delay)
2380 {
2383  "New inbound delay %s\n",
2385  GNUNET_NO));
2386  if (s->recv_wakeup_task != NULL)
2387  {
2389  s->recv_wakeup_task
2391  &client_wake_up,
2392  s);
2393  }
2394 }
2395 
2396 
2406 static int
2408  const struct GNUNET_PeerIdentity *peer,
2409  void *value)
2410 {
2411  struct HTTP_Client_Plugin *plugin = cls;
2412  struct GNUNET_ATS_Session *session = value;
2413 
2415  session,
2418  session,
2419  GNUNET_TRANSPORT_SS_UP); /* FIXME: or handshake? */
2420  return GNUNET_OK;
2421 }
2422 
2423 
2436 static void
2439  void *sic_cls)
2440 {
2441  struct HTTP_Client_Plugin *plugin = cls;
2442 
2443  plugin->sic = sic;
2444  plugin->sic_cls = sic_cls;
2445  if (NULL != sic)
2446  {
2449  plugin);
2450  /* signal end of first iteration */
2451  sic (sic_cls, NULL, NULL);
2452  }
2453 }
2454 
2455 
2459 void *
2461 {
2464  struct HTTP_Client_Plugin *plugin;
2465 
2466  if (NULL == env->receive)
2467  {
2468  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
2469  initialize the plugin or the API */
2471  api->cls = NULL;
2475  return api;
2476  }
2477 
2479  plugin->env = env;
2481  GNUNET_YES);
2483  api->cls = plugin;
2484  api->send = &http_client_plugin_send;
2498 #if BUILD_HTTPS
2499  plugin->name = "transport-https_client";
2500  plugin->protocol = "https";
2501 #else
2502  plugin->name = "transport-http_client";
2503  plugin->protocol = "http";
2504 #endif
2505  plugin->last_tag = 1;
2506 
2508  {
2510  return NULL;
2511  }
2512 
2513  /* Start client */
2515  {
2517  return NULL;
2518  }
2519  return api;
2520 }
2521 
2522 
2523 /* end of plugin_transport_http_client.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static int res
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
struct TestcasePlugin * plugin
The process handle to the testbed service.
static char * address
GNS address for this phone.
static CURL * curl
Current CURL handle.
static curl_proxytype proxy_type
Proxy type we are using (can be NULL).
struct GNUNET_HashCode key
The key used in the DHT.
uint32_t data
The data value.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static char * value
Value of the record to add/remove.
enum State state
current state of profiling
#define info
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
library to make it easy to download JSON replies over HTTP
Constants for network protocols.
Transport service plugin API.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
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.
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".
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.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
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).
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.
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.
enum GNUNET_GenericReturnValue 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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
#define GNUNET_HELLO_address_free(addr)
Free an address.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:99
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:112
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MIN(a, b)
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1170
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1186
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:1040
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:39
@ GNUNET_NT_WAN
Wide area network (i.e.
Definition: gnunet_nt_lib.h:58
@ GNUNET_NT_UNSPECIFIED
Category of last resort.
Definition: gnunet_nt_lib.h:43
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:1299
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:1830
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
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:1272
enum GNUNET_GenericReturnValue 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:101
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:404
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:86
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
enum GNUNET_GenericReturnValue GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
Convert the utf-8 input string to upper case.
Definition: strings.c:471
#define GNUNET_TIME_UNIT_SECONDS
One second.
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:405
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
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:316
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:484
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
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:569
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:421
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 ...
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".
GNUNET_TRANSPORT_SessionState
Possible states of a session in a plugin.
@ GNUNET_TRANSPORT_SS_INIT
The session was created (first call for each session object).
@ GNUNET_TRANSPORT_SS_DONE
Session is being torn down and about to disappear.
@ GNUNET_TRANSPORT_SS_UP
Session is fully UP.
@ GNUNET_TRANSPORT_SS_UPDATE
This is just an update about the session, the state did not change.
#define max(x, y)
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
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.
static int client_connect_put(struct GNUNET_ATS_Session *s)
Connect a HTTP put request.
#define PLUGIN_NAME
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 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.
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 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 LIBGNUNET_PLUGIN_TRANSPORT_DONE
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.
static int client_configure_plugin(struct HTTP_Client_Plugin *plugin)
Configure plugin.
static void client_session_timeout(void *cls)
Session was idle, so disconnect it.
HTTP_PUT_REQUEST_STATE
State of a HTTP PUT request.
@ H_TMP_RECONNECT_REQUIRED
Send request while temporary disconnect, reconnect.
@ H_PAUSED
Paused, nothing to send.
@ H_DISCONNECTED
Disconnected.
@ H_CONNECTED
Connected.
@ H_TMP_DISCONNECTING
Temporary disconnect in progress due to inactivity.
@ H_NOT_CONNECTED
Just created, not yet connected.
@ H_TMP_DISCONNECTED
Temporarily disconnected.
#define PUT_DISCONNECT_TIMEOUT
static int client_start(struct HTTP_Client_Plugin *plugin)
Setup http_client plugin.
static int client_schedule(struct HTTP_Client_Plugin *plugin, int now)
Function setting up file descriptors and scheduling task to run.
static int http_client_plugin_session_disconnect(void *cls, struct GNUNET_ATS_Session *s)
Disconnect a session.
static unsigned int http_client_query_keepalive_factor(void *cls)
Function that is called to get the keepalive factor.
static int destroy_session_cb(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Callback to destroys all sessions on exit.
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.
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.
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...
#define LIBGNUNET_PLUGIN_TRANSPORT_INIT
static int client_connect(struct GNUNET_ATS_Session *s)
Connect both PUT and GET request for a session.
#define HTTP_STAT_STR_CONNECTIONS
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.
static void http_client_plugin_setup_monitor(void *cls, GNUNET_TRANSPORT_SessionInfoCallback sic, void *sic_cls)
Begin monitoring sessions of a plugin.
static int client_receive_mst_cb(void *cls, const struct GNUNET_MessageHeader *message)
Callback for message stream tokenizer.
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...
static void client_reschedule_session_timeout(struct GNUNET_ATS_Session *s)
Increment session timeout due to activity for session s.
#define LOG(kind,...)
static int client_connect_get(struct GNUNET_ATS_Session *s)
Connect GET request.
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 int send_session_info_iter(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Return information about the given session to the monitor callback.
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 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.
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.
static void client_run(void *cls)
Task performing curl operations.
static void client_wake_up(void *cls)
Wake up a curl handle which was suspended.
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 void client_delete_session(struct GNUNET_ATS_Session *s)
Delete session s.
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 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.
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.
const char * http_common_plugin_address_to_url(void *cls, const void *addr, size_t addrlen)
FIXME.
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.
struct sockaddr * http_common_socket_from_address(const void *addr, size_t addrlen, int *res)
Create a socketaddr from a HTTP address.
#define HTTP_CLIENT_SESSION_TIMEOUT
@ HTTP_OPTIONS_VERIFY_CERTIFICATE
Verify X509 server certificate, it should be valid.
@ HTTP_OPTIONS_TCP_STEALTH
Enable TCP Stealth-style port knocking.
#define HTTP_CLIENT_NOT_VALIDATED_TIMEOUT
#define TIMEOUT_LOG
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
Closure for session_lookup_client_by_address().
const struct GNUNET_HELLO_Address * address
Address we are looking for.
struct GNUNET_ATS_Session * ret
Session that was found.
Session handle for connections.
struct GNUNET_PeerIdentity target
To whom are we talking to.
struct Plugin * plugin
Pointer to the global plugin struct.
unsigned int msgs_in_queue
Number of messages waiting for transmission to this peer.
struct GNUNET_MessageStreamTokenizer * msg_tk
Message stream tokenizer for incoming data.
struct GNUNET_TIME_Absolute timeout
When does this session time out.
struct HTTP_Message * msg_tail
previous pointer for double linked list
struct GNUNET_HELLO_Address * address
Address.
struct HTTP_Message * msg_head
next pointer for double linked list
enum GNUNET_NetworkType scope
ATS network type.
struct RequestHandle get
Handle for the HTTP GET request.
unsigned long long bytes_in_queue
Number of bytes waiting for transmission to this peer.
char * url
The URL to connect to.
struct RequestHandle put
Handle for the HTTP PUT request.
size_t overhead
Outbound overhead due to HTTP connection Add to next message of this session when calling callback.
struct GNUNET_SCHEDULER_Task * recv_wakeup_task
Task to wake up client receive handle when receiving is allowed again.
struct GNUNET_SCHEDULER_Task * put_disconnect_task
Session timeout task.
struct GNUNET_TIME_Absolute next_receive
Absolute time when to receive data again Used for receive throttling.
struct GNUNET_SCHEDULER_Task * timeout_task
Session timeout task.
struct GNUNET_SERVER_MessageStreamTokenizer * msg_tk
Message stream tokenizer for incoming data.
Internal representation of the hash map.
An address for communicating with a peer.
size_t address_length
Number of bytes in address.
struct GNUNET_PeerIdentity peer
For which peer is this an address?
const void * address
Binary representation of the address (plugin-specific).
Header for all communications.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Handle to a message stream tokenizer.
Definition: mst.c:45
collection of IO descriptors
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
The transport service will pass a pointer to a struct of this type as the first and only argument to ...
void * cls
Closure for the various callbacks.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
void * cls
Closure for all of the callbacks.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
GNUNET_TRANSPORT_UpdateInboundDelay update_inbound_delay
Function that will be called whenever the transport service wants to notify the plugin that the inbou...
GNUNET_TRANSPORT_SessionMonitorSetup setup_monitor
Function to monitor the sessions managed by the plugin.
GNUNET_TRANSPORT_DisconnectPeerFunction disconnect_peer
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
GNUNET_TRANSPORT_GetNetworkTypeForAddress get_network_for_address
Function to obtain the network type for an address.
GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
GNUNET_TRANSPORT_QueryKeepaliveFactorFunction query_keepalive_factor
Function that is used to query keepalive factor.
GNUNET_TRANSPORT_AddressPrettyPrinter address_pretty_printer
Function to pretty-print addresses.
GNUNET_TRANSPORT_AddressToString address_to_string
Function that will be called to convert a binary address to a string (numeric conversion only).
GNUNET_TRANSPORT_GetNetworkType get_network
Function to obtain the network type for a session.
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
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_StringToAddress string_to_address
Function that will be called to convert a string address to binary (numeric conversion only).
GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout
Function that will be called whenever the transport service wants to notify the plugin that a session...
Information about a plugin's session.
Encapsulation of all of the state of the plugin.
int emulate_xhr
Should we emulate an XHR client for testing?
unsigned int cur_requests
Current number of sockets the plugin can use Each http connections are two requests.
CURLM * curl_multi_handle
cURL Multihandle
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.
uint32_t options
My options to be included in the address.
char * proxy_hostname
Proxy configuration: hostname or ip of the proxy server.
int proxy_use_httpproxytunnel
Use proxy tunneling: Tunnel all operations through a given HTTP instead of have the proxy evaluate th...
curl_proxytype proxytype
Type of proxy server:
char * proxy_password
Password for the proxy server.
void * sic_cls
Closure for sic.
struct GNUNET_TRANSPORT_PluginEnvironment * env
Our environment.
struct GNUNET_CONTAINER_MultiPeerMap * sessions
Open sessions.
struct GNUNET_SCHEDULER_Task * client_perform_task
curl perform task
char * proxy_username
Username for the proxy server.
uint32_t last_tag
Last used unique HTTP connection tag.
unsigned int max_requests
Maximum number of sockets the plugin can use Each http connections are two requests.
Message to send using http.
size_t size
buffer length
struct HTTP_Message * next
next pointer for double linked list
size_t pos
amount of data already sent
GNUNET_TRANSPORT_TransmitContinuation transmit_cont
Continuation function to call once the transmission buffer has again space available.
void * transmit_cont_cls
Closure for transmit_cont.
char * buf
buffer containing data to send
struct HTTP_Message * prev
previous pointer for double linked list
HTTP addresses including a full URI.
uint32_t options
Address options see enum HttpAddressOptions
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
char * protocol
Plugin protocol http, https.
The request handle.
enum HTTP_PUT_REQUEST_STATE state
Current state of this request.
struct GNUNET_ATS_Session * s
The related session.
CURL * easyhandle
The curl easy handle.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.