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 
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 {
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;
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 
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 
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;
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 */
632  timeout, grs, gws,
633  &client_run, plugin);
636  return GNUNET_OK;
637 }
638 
639 
640 #if VERBOSE_CURL
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);
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  }
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 
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--;
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  }
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  {
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 occurred */
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 progress, 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);
1449 }
1450 
1451 
1452 #ifdef TCP_STEALTH
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  {
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 
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 */
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;
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  }
2115  s,
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  {
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 
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 */
2320  plugin->proxy_use_httpproxytunnel
2322  plugin->name,
2323  "PROXY_HTTP_TUNNELING");
2324  if (GNUNET_SYSERR == plugin->proxy_use_httpproxytunnel)
2325  plugin->proxy_use_httpproxytunnel = GNUNET_NO;
2326 
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 
2427  session,
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  initialize the plugin or the API */
2483  api->cls = NULL;
2487  return api;
2488  }
2489 
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 
2520  {
2522  return NULL;
2523  }
2524 
2525  /* Start client */
2527  {
2529  return NULL;
2530  }
2531  return api;
2532 }
2533 
2534 
2535 /* 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 Plugin * 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
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
#define GNUNET_log(kind,...)
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
#define GNUNET_MIN(a, b)
library to make it easy to download JSON replies over HTTP
#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_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
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.
@ 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:109
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:130
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:1245
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1261
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:1115
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:36
@ GNUNET_NT_WAN
Wide area network (i.e.
Definition: gnunet_nt_lib.h:55
@ GNUNET_NT_UNSPECIFIED
Category of last resort.
Definition: gnunet_nt_lib.h:40
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
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 * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
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
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:411
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:85
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
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.
void GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
Convert the utf-8 input string to upper case.
Definition: strings.c:463
#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:232
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86
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:181
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:311
#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:557
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:248
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:67
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
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:35
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.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
void * cls
Closure to use for callbacks.
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:44
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:135
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.
struct GNUNET_TIME_Absolute receive_delay
Until when does this plugin refuse to receive to manage staying within the inbound quota?...
const struct GNUNET_HELLO_Address * address
Address used by the session.
int is_inbound
GNUNET_YES if this is an inbound connection, GNUNET_NO if this is an outbound connection,...
struct GNUNET_TIME_Absolute session_timeout
At what time will this session timeout (unless activity happens)?
uint32_t num_bytes_pending
Number of bytes pending transmission for this session.
enum GNUNET_TRANSPORT_SessionState state
New state of the session.
uint32_t num_msg_pending
Number of messages pending transmission for this 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_SCHEDULER_Task * client_perform_task
curl perform task
void * sic_cls
Closure for sic.
uint32_t last_tag
Last used unique HTTP connection tag.
struct GNUNET_ATS_Session * sessions
List of open sessions (or peer map, or...)
char * name
Plugin name.
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
char * protocol
Plugin protocol http, https.
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.
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.