GNUnet  0.10.x
plugin_transport_http_client.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2002-2014 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
28 #if BUILD_HTTPS
29 #define PLUGIN_NAME "https_client"
30 #define HTTP_STAT_STR_CONNECTIONS "# HTTPS client connections"
31 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_https_client_init
32 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_https_client_done
33 #else
34 #define PLUGIN_NAME "http_client"
35 #define HTTP_STAT_STR_CONNECTIONS "# HTTP client connections"
36 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_http_client_init
37 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_client_done
38 #endif
39 
40 #define VERBOSE_CURL GNUNET_NO
41 
42 #define PUT_DISCONNECT_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 1)
43 
44 #define ENABLE_PUT GNUNET_YES
45 #define ENABLE_GET GNUNET_YES
46 
47 #include "platform.h"
48 #include "gnunet_util_lib.h"
49 #include "gnunet_protocols.h"
52 /* Just included for the right curl.h */
53 #include "gnunet_curl_lib.h"
54 
55 
56 #define LOG(kind, ...) GNUNET_log_from(kind, PLUGIN_NAME, __VA_ARGS__)
57 
61 struct HTTP_Client_Plugin;
62 
71 
76 
81 
86 
91 
96 
101 };
102 
106 struct HTTP_Message {
110  struct HTTP_Message *next;
111 
115  struct HTTP_Message *prev;
116 
120  char *buf;
121 
128 
132  void *transmit_cont_cls;
133 
137  size_t pos;
138 
142  size_t size;
143 };
144 
145 
149 struct GNUNET_ATS_Session;
150 
151 
156 struct RequestHandle {
161 
165  CURL *easyhandle;
166 
171 };
172 
173 
177 struct GNUNET_ATS_Session {
181  char *url;
182 
187 
192 
196  struct RequestHandle put;
197 
201  struct RequestHandle get;
202 
206  struct HTTP_Message *msg_head;
207 
211  struct HTTP_Message *msg_tail;
212 
217 
222 
227 
231  struct GNUNET_SCHEDULER_Task *recv_wakeup_task;
232 
237  struct GNUNET_TIME_Absolute next_receive;
238 
243 
247  unsigned long long bytes_in_queue;
248 
253  size_t overhead;
254 
258  unsigned int msgs_in_queue;
259 
264 };
265 
266 
275 
280 
285 
289  void *sic_cls;
290 
294  char *name;
295 
299  char *protocol;
300 
305 
310 
315 
320 
325 
333  curl_proxytype proxytype;
334 
343 
347  uint32_t options;
348 
353  unsigned int max_requests;
354 
359  unsigned int cur_requests;
360 
364  uint32_t last_tag;
365 
369  uint16_t use_ipv6;
370 
374  uint16_t use_ipv4;
375 
380 };
381 
382 
390 static int
392 
393 
402 static void
404  struct GNUNET_ATS_Session *session,
406 {
407  struct GNUNET_TRANSPORT_SessionInfo info;
408 
409  if (NULL == plugin->sic)
410  return;
411  memset(&info, 0, sizeof(info));
412  info.state = state;
413  info.is_inbound = GNUNET_NO;
414  info.num_msg_pending = session->msgs_in_queue;
415  info.num_bytes_pending = session->bytes_in_queue;
416  info.receive_delay = session->next_receive;
417  info.session_timeout = session->timeout;
418  info.address = session->address;
419  plugin->sic(plugin->sic_cls,
420  session,
421  &info);
422 }
423 
424 
430 static void
432 {
433  struct HTTP_Client_Plugin *plugin = s->plugin;
434  struct HTTP_Message *pos;
435  struct HTTP_Message *next;
436  CURLMcode mret;
437 
438  if (NULL != s->timeout_task)
439  {
441  s->timeout_task = NULL;
443  }
444  if (NULL != s->put_disconnect_task)
445  {
447  s->put_disconnect_task = NULL;
448  }
449  if (NULL != s->recv_wakeup_task)
450  {
452  s->recv_wakeup_task = NULL;
453  }
456  &s->address->peer,
457  s));
458  if (NULL != s->put.easyhandle)
459  {
461  "Session %p/request %p: disconnecting PUT request to peer `%s'\n",
462  s,
463  s->put.easyhandle,
464  GNUNET_i2s(&s->address->peer));
465 
466  /* remove curl handle from multi handle */
467  mret = curl_multi_remove_handle(plugin->curl_multi_handle,
468  s->put.easyhandle);
469  GNUNET_break(CURLM_OK == mret);
470  curl_easy_cleanup(s->put.easyhandle);
471  GNUNET_assert(plugin->cur_requests > 0);
472  plugin->cur_requests--;
473  s->put.easyhandle = NULL;
474  }
475  if (NULL != s->get.easyhandle)
476  {
478  "Session %p/request %p: disconnecting GET request to peer `%s'\n",
479  s, s->get.easyhandle,
480  GNUNET_i2s(&s->address->peer));
481  /* remove curl handle from multi handle */
482  mret = curl_multi_remove_handle(plugin->curl_multi_handle,
483  s->get.easyhandle);
484  GNUNET_break(CURLM_OK == mret);
485  curl_easy_cleanup(s->get.easyhandle);
486  GNUNET_assert(plugin->cur_requests > 0);
487  plugin->cur_requests--;
488  s->get.easyhandle = NULL;
489  }
490 
493  plugin->cur_requests,
494  GNUNET_NO);
495  next = s->msg_head;
496  while (NULL != (pos = next))
497  {
498  next = pos->next;
500  s->msg_tail,
501  pos);
503  s->msgs_in_queue--;
504  GNUNET_assert(pos->size <= s->bytes_in_queue);
505  s->bytes_in_queue -= pos->size;
506  if (NULL != pos->transmit_cont)
508  &s->address->peer,
510  pos->size,
511  pos->pos + s->overhead);
512  s->overhead = 0;
513  GNUNET_free(pos);
514  }
515  GNUNET_assert(0 == s->msgs_in_queue);
516  GNUNET_assert(0 == s->bytes_in_queue);
517  notify_session_monitor(plugin,
518  s,
520  if (NULL != s->msg_tk)
521  {
523  s->msg_tk = NULL;
524  }
526  GNUNET_free(s->url);
527  GNUNET_free(s);
528 }
529 
530 
536 static void
538 {
539  GNUNET_assert(NULL != s->timeout_task);
541 }
542 
543 
550 static void
551 client_run(void *cls);
552 
553 
561 static int
563  int now)
564 {
565  fd_set rs;
566  fd_set ws;
567  fd_set es;
568  int max;
569  struct GNUNET_NETWORK_FDSet *grs;
570  struct GNUNET_NETWORK_FDSet *gws;
571  long to;
572  CURLMcode mret;
573  struct GNUNET_TIME_Relative timeout;
574 
575  /* Cancel previous scheduled task */
576  if (plugin->client_perform_task != NULL)
577  {
579  plugin->client_perform_task = NULL;
580  }
581  max = -1;
582  FD_ZERO(&rs);
583  FD_ZERO(&ws);
584  FD_ZERO(&es);
585  mret = curl_multi_fdset(plugin->curl_multi_handle, &rs, &ws, &es, &max);
586  if (mret != CURLM_OK)
587  {
589  _("%s failed at %s:%d: `%s'\n"),
590  "curl_multi_fdset",
591  __FILE__,
592  __LINE__,
593  curl_multi_strerror(mret));
594  return GNUNET_SYSERR;
595  }
596  mret = curl_multi_timeout(plugin->curl_multi_handle, &to);
597  if (-1 == to)
599  else
601  if (now == GNUNET_YES)
603 
604  if (CURLM_OK != mret)
605  {
607  _("%s failed at %s:%d: `%s'\n"),
608  "curl_multi_timeout", __FILE__, __LINE__,
609  curl_multi_strerror(mret));
610  return GNUNET_SYSERR;
611  }
612 
615  GNUNET_NETWORK_fdset_copy_native(grs, &rs, max + 1);
616  GNUNET_NETWORK_fdset_copy_native(gws, &ws, max + 1);
617 
618  /* Schedule task to run when select is ready to read or write */
619  plugin->client_perform_task =
621  timeout, grs, gws,
622  &client_run, plugin);
625  return GNUNET_OK;
626 }
627 
628 
629 #if VERBOSE_CURL
630 
640 static int
641 client_log(CURL *curl,
642  curl_infotype type,
643  const char *data,
644  size_t size,
645  void *cls)
646 {
647  struct RequestHandle *ch = cls;
648  const char *ttype = "UNSPECIFIED";
649  char text[size + 2];
650 
651  if (!((CURLINFO_TEXT == type) ||
652  (CURLINFO_HEADER_IN == type) ||
653  (CURLINFO_HEADER_OUT == type)))
654  return 0;
655  switch (type)
656  {
657  case CURLINFO_TEXT:
658  ttype = "TEXT";
659  break;
660 
661  case CURLINFO_HEADER_IN:
662  ttype = "HEADER_IN";
663  break;
664 
665  case CURLINFO_HEADER_OUT:
666  ttype = "HEADER_OUT";
667  /* Overhead*/
668  GNUNET_assert(NULL != ch);
669  GNUNET_assert(NULL != ch->easyhandle);
670  GNUNET_assert(NULL != ch->s);
671  ch->s->overhead += size;
672  break;
673 
674  default:
675  ttype = "UNSPECIFIED";
676  break;
677  }
678  GNUNET_memcpy(text, data, size);
679  if (text[size - 1] == '\n')
680  {
681  text[size] = '\0';
682  }
683  else
684  {
685  text[size] = '\n';
686  text[size + 1] = '\0';
687  }
689  "Request %p %s: %s",
690  ch->easyhandle,
691  ttype,
692  text);
693  return 0;
694 }
695 #endif
696 
703 static int
705 
706 
713 static int
715 
716 
744 static ssize_t
746  struct GNUNET_ATS_Session *s,
747  const char *msgbuf,
748  size_t msgbuf_size,
749  unsigned int priority,
750  struct GNUNET_TIME_Relative to,
752  void *cont_cls)
753 {
754  struct HTTP_Client_Plugin *plugin = cls;
755  struct HTTP_Message *msg;
756  char *stat_txt;
757 
759  "Session %p/request %p: Sending message with %u to peer `%s' \n",
760  s,
761  s->put.easyhandle,
762  msgbuf_size,
763  GNUNET_i2s(&s->address->peer));
764 
765  /* create new message and schedule */
766  msg = GNUNET_malloc(sizeof(struct HTTP_Message) + msgbuf_size);
767  msg->size = msgbuf_size;
768  msg->buf = (char *)&msg[1];
769  msg->transmit_cont = cont;
770  msg->transmit_cont_cls = cont_cls;
771  GNUNET_memcpy(msg->buf,
772  msgbuf,
773  msgbuf_size);
775  s->msg_tail,
776  msg);
777  s->msgs_in_queue++;
778  s->bytes_in_queue += msg->size;
779 
780  GNUNET_asprintf(&stat_txt,
781  "# bytes currently in %s_client buffers",
782  plugin->protocol);
784  stat_txt, msgbuf_size, GNUNET_NO);
785  GNUNET_free(stat_txt);
786  notify_session_monitor(plugin,
787  s,
789  if (H_TMP_DISCONNECTING == s->put.state)
790  {
791  /* PUT request is currently getting disconnected */
794  "Session %p/request %p: currently disconnecting, reconnecting immediately\n",
795  s,
796  s->put.easyhandle);
797  return msgbuf_size;
798  }
799  if (H_PAUSED == s->put.state)
800  {
801  /* PUT request was paused, unpause */
804  s->put_disconnect_task = NULL;
806  "Session %p/request %p: unpausing request\n",
807  s, s->put.easyhandle);
808  s->put.state = H_CONNECTED;
809  if (NULL != s->put.easyhandle)
810  curl_easy_pause(s->put.easyhandle, CURLPAUSE_CONT);
811  }
812  else if (H_TMP_DISCONNECTED == s->put.state)
813  {
814  /* PUT request was disconnected, reconnect */
815  LOG(GNUNET_ERROR_TYPE_DEBUG, "Session %p: Reconnecting PUT request\n", s);
816  GNUNET_break(NULL == s->put.easyhandle);
818  {
819  /* Could not reconnect */
821  return GNUNET_SYSERR;
822  }
823  }
825  return msgbuf_size;
826 }
827 
828 
836 static int
838  struct GNUNET_ATS_Session *s)
839 {
840  struct HTTP_Client_Plugin *plugin = cls;
841 
843  "Session %p: notifying transport about ending session\n",
844  s);
845  plugin->env->session_end(plugin->env->cls,
846  s->address,
847  s);
849 
850  /* Re-schedule since handles have changed */
851  if (NULL != plugin->client_perform_task)
852  {
854  plugin->client_perform_task = NULL;
855  }
856  client_schedule(plugin, GNUNET_YES);
857 
858  return GNUNET_OK;
859 }
860 
861 
870 static unsigned int
872 {
873  return 3;
874 }
875 
876 
885 static int
887  const struct GNUNET_PeerIdentity *peer,
888  void *value)
889 {
890  struct HTTP_Client_Plugin *plugin = cls;
891  struct GNUNET_ATS_Session *session = value;
892 
893  http_client_plugin_session_disconnect(plugin, session);
894  return GNUNET_OK;
895 }
896 
897 
906 static void
908  const struct GNUNET_PeerIdentity *target)
909 {
910  struct HTTP_Client_Plugin *plugin = cls;
911 
913  "Transport tells me to disconnect `%s'\n",
914  GNUNET_i2s(target));
916  target,
918  plugin);
919 }
920 
921 
930 
935 };
936 
937 
946 static int
948  const struct GNUNET_PeerIdentity *key,
949  void *value)
950 {
951  struct GNUNET_ATS_SessionClientCtx *sc_ctx = cls;
952  struct GNUNET_ATS_Session *s = value;
953 
954  if (0 == GNUNET_HELLO_address_cmp(sc_ctx->address,
955  s->address))
956  {
957  sc_ctx->ret = s;
958  return GNUNET_NO;
959  }
960  return GNUNET_YES;
961 }
962 
963 
971 static struct GNUNET_ATS_Session *
973  const struct GNUNET_HELLO_Address *address)
974 {
975  struct GNUNET_ATS_SessionClientCtx sc_ctx;
976 
977  sc_ctx.address = address;
978  sc_ctx.ret = NULL;
981  &sc_ctx);
982  return sc_ctx.ret;
983 }
984 
985 
993 static void
995 {
996  struct GNUNET_ATS_Session *s = cls;
997 
998  s->put_disconnect_task = NULL;
1000  "Session %p/request %p: will be disconnected due to no activity\n",
1001  s, s->put.easyhandle);
1003  if (NULL != s->put.easyhandle)
1004  curl_easy_pause(s->put.easyhandle,
1005  CURLPAUSE_CONT);
1007 }
1008 
1009 
1020 static size_t
1021 client_send_cb(void *stream,
1022  size_t size,
1023  size_t nmemb,
1024  void *cls)
1025 {
1026  struct GNUNET_ATS_Session *s = cls;
1027  struct HTTP_Client_Plugin *plugin = s->plugin;
1028  struct HTTP_Message *msg = s->msg_head;
1029  size_t len;
1030  char *stat_txt;
1031 
1032  if (H_TMP_DISCONNECTING == s->put.state)
1033  {
1035  "Session %p/request %p: disconnect due to inactivity\n",
1036  s, s->put.easyhandle);
1037  return 0;
1038  }
1039 
1040  if (NULL == msg)
1041  {
1042  if (GNUNET_YES == plugin->emulate_xhr)
1043  {
1045  "Session %p/request %p: PUT request finished\n",
1046  s,
1047  s->put.easyhandle);
1049  return 0;
1050  }
1051 
1052  /* We have nothing to send, so pause PUT request */
1054  "Session %p/request %p: nothing to send, suspending\n",
1055  s,
1056  s->put.easyhandle);
1060  s);
1061  s->put.state = H_PAUSED;
1062  return CURL_READFUNC_PAUSE;
1063  }
1064  /* data to send */
1065  GNUNET_assert(msg->pos < msg->size);
1066  /* calculate how much fits in buffer */
1067  len = GNUNET_MIN(msg->size - msg->pos,
1068  size * nmemb);
1069  GNUNET_memcpy(stream,
1070  &msg->buf[msg->pos],
1071  len);
1072  msg->pos += len;
1073  if (msg->pos == msg->size)
1074  {
1076  "Session %p/request %p: sent message with %u bytes sent, removing message from queue\n",
1077  s,
1078  s->put.easyhandle,
1079  msg->size,
1080  msg->pos);
1081  /* Calling transmit continuation */
1083  s->msg_tail,
1084  msg);
1085  GNUNET_assert(0 < s->msgs_in_queue);
1086  s->msgs_in_queue--;
1087  GNUNET_assert(msg->size <= s->bytes_in_queue);
1088  s->bytes_in_queue -= msg->size;
1089  if (NULL != msg->transmit_cont)
1090  msg->transmit_cont(msg->transmit_cont_cls,
1091  &s->address->peer,
1092  GNUNET_OK,
1093  msg->size,
1094  msg->size + s->overhead);
1095  s->overhead = 0;
1096  GNUNET_free(msg);
1097  }
1098  notify_session_monitor(plugin,
1099  s,
1101  GNUNET_asprintf(&stat_txt,
1102  "# bytes currently in %s_client buffers",
1103  plugin->protocol);
1105  stat_txt,
1106  -len,
1107  GNUNET_NO);
1108  GNUNET_free(stat_txt);
1109  GNUNET_asprintf(&stat_txt,
1110  "# bytes transmitted via %s_client",
1111  plugin->protocol);
1113  stat_txt,
1114  len,
1115  GNUNET_NO);
1116  GNUNET_free(stat_txt);
1117  return len;
1118 }
1119 
1120 
1126 static void
1127 client_wake_up(void *cls)
1128 {
1129  struct GNUNET_ATS_Session *s = cls;
1130 
1131  s->recv_wakeup_task = NULL;
1133  "Session %p/request %p: Waking up GET handle\n",
1134  s, s->get.easyhandle);
1135  if (H_PAUSED == s->put.state)
1136  {
1137  /* PUT request was paused, unpause */
1138  GNUNET_assert(s->put_disconnect_task != NULL);
1140  s->put_disconnect_task = NULL;
1141  s->put.state = H_CONNECTED;
1142  if (NULL != s->put.easyhandle)
1143  curl_easy_pause(s->put.easyhandle, CURLPAUSE_CONT);
1144  }
1145  if (NULL != s->get.easyhandle)
1146  curl_easy_pause(s->get.easyhandle, CURLPAUSE_CONT);
1147 }
1148 
1149 
1157 static int
1159  const struct GNUNET_MessageHeader *message)
1160 {
1161  struct GNUNET_ATS_Session *s = cls;
1162  struct HTTP_Client_Plugin *plugin;
1163  struct GNUNET_TIME_Relative delay;
1164  char *stat_txt;
1165 
1166  plugin = s->plugin;
1167  delay = s->plugin->env->receive(plugin->env->cls,
1168  s->address,
1169  s,
1170  message);
1171  GNUNET_asprintf(&stat_txt,
1172  "# bytes received via %s_client",
1173  plugin->protocol);
1175  stat_txt,
1176  ntohs(message->size),
1177  GNUNET_NO);
1178  GNUNET_free(stat_txt);
1179 
1181  if (GNUNET_TIME_absolute_get().abs_value_us < s->next_receive.abs_value_us)
1182  {
1184  "Client: peer `%s' address `%s' next read delayed for %s\n",
1185  GNUNET_i2s(&s->address->peer),
1187  s->address->address,
1188  s->address->address_length),
1190  GNUNET_YES));
1191  }
1193  return GNUNET_OK;
1194 }
1195 
1196 
1207 static size_t
1208 client_receive_put(void *stream,
1209  size_t size,
1210  size_t nmemb,
1211  void *cls)
1212 {
1213  return size * nmemb;
1214 }
1215 
1216 
1227 static size_t
1228 client_receive(void *stream,
1229  size_t size,
1230  size_t nmemb,
1231  void *cls)
1232 {
1233  struct GNUNET_ATS_Session *s = cls;
1234  struct GNUNET_TIME_Absolute now;
1235  size_t len = size * nmemb;
1236 
1238  "Session %p / request %p: Received %u bytes from peer `%s'\n",
1239  s,
1240  s->get.easyhandle,
1241  len,
1242  GNUNET_i2s(&s->address->peer));
1243  now = GNUNET_TIME_absolute_get();
1244  if (now.abs_value_us < s->next_receive.abs_value_us)
1245  {
1247  struct GNUNET_TIME_Relative delta
1249 
1251  "Session %p / request %p: No inbound bandwidth available! Next read was delayed for %s\n",
1252  s,
1253  s->get.easyhandle,
1255  GNUNET_YES));
1256  if (s->recv_wakeup_task != NULL)
1257  {
1259  s->recv_wakeup_task = NULL;
1260  }
1261  s->recv_wakeup_task
1263  &client_wake_up,
1264  s);
1265  return CURL_WRITEFUNC_PAUSE;
1266  }
1267  if (NULL == s->msg_tk)
1269  s);
1271  stream,
1272  len,
1273  GNUNET_NO,
1274  GNUNET_NO);
1275  return len;
1276 }
1277 
1278 
1284 static void
1285 client_run(void *cls)
1286 {
1287  struct HTTP_Client_Plugin *plugin = cls;
1288  int running;
1289  long http_statuscode;
1290  CURLMcode mret;
1291  CURLMsg *msg;
1292  int put_request; /* GNUNET_YES if easy handle is put, GNUNET_NO for get */
1293  int msgs_left;
1294 
1295  plugin->client_perform_task = NULL;
1296  /* While data are available or timeouts occured */
1297  do
1298  {
1299  running = 0;
1300  /* Perform operations for all handles */
1301  mret = curl_multi_perform(plugin->curl_multi_handle, &running);
1302 
1303  /* Get additional information for all handles */
1304  while (NULL != (msg = curl_multi_info_read(plugin->curl_multi_handle, &msgs_left)))
1305  {
1306  CURL *easy_h = msg->easy_handle;
1307  struct GNUNET_ATS_Session *s = NULL;
1308  char *d = NULL; /* curl requires 'd' to be a 'char *' */
1309 
1310  GNUNET_assert(NULL != easy_h);
1311 
1312  /* Obtain session from easy handle */
1313  GNUNET_assert(CURLE_OK == curl_easy_getinfo(easy_h, CURLINFO_PRIVATE, &d));
1314  s = (struct GNUNET_ATS_Session *)d;
1315  GNUNET_assert(NULL != s);
1316 
1317  if (msg->msg != CURLMSG_DONE)
1318  continue; /* This should not happen */
1319 
1320  /* Get HTTP response code */
1321  GNUNET_break(CURLE_OK == curl_easy_getinfo(easy_h,
1322  CURLINFO_RESPONSE_CODE, &http_statuscode));
1323 
1324  if (easy_h == s->put.easyhandle)
1325  put_request = GNUNET_YES;
1326  else
1327  put_request = GNUNET_NO;
1328 
1329  /* Log status of terminated request */
1330  if ((0 != msg->data.result) || (http_statuscode != 200))
1332  "Session %p/request %p: %s request to `%s' ended with status %i reason %i: `%s'\n",
1333  s, msg->easy_handle,
1334  (GNUNET_YES == put_request) ? "PUT" : "GET",
1335  GNUNET_i2s(&s->address->peer),
1336  http_statuscode,
1337  msg->data.result,
1338  curl_easy_strerror(msg->data.result));
1339  else
1341  "Session %p/request %p: %s request to `%s' ended normal\n",
1342  s, msg->easy_handle,
1343  (GNUNET_YES == put_request) ? "PUT" : "GET",
1344  GNUNET_i2s(&s->address->peer));
1345 
1346  /* Remove easy handle from multi handle */
1347  curl_multi_remove_handle(plugin->curl_multi_handle, easy_h);
1348 
1349  /* Clean up easy handle */
1350  curl_easy_cleanup(easy_h);
1351 
1352  /* Remove information */
1353  GNUNET_assert(plugin->cur_requests > 0);
1354  plugin->cur_requests--;
1356  "%s request to %s done, number of requests decreased to %u\n",
1357  (GNUNET_YES == put_request) ? "PUT" : "GET",
1358  s->url,
1359  plugin->cur_requests);
1360 
1361  if (GNUNET_YES == put_request)
1362  {
1363  /* Clean up a PUT request */
1364  s->put.easyhandle = NULL;
1365  s->put.s = NULL;
1366 
1367  switch (s->put.state)
1368  {
1369  case H_NOT_CONNECTED:
1370  case H_DISCONNECTED:
1371  case H_TMP_DISCONNECTED:
1372  /* This must not happen */
1373  GNUNET_break(0);
1374  break;
1375 
1377  /* Transport called send while disconnect in progess, reconnect */
1379  {
1380  /* Reconnect failed, disconnect session */
1382  }
1383  break;
1384 
1385  case H_TMP_DISCONNECTING:
1386  /* PUT gets temporarily disconnected */
1388  break;
1389 
1390  case H_PAUSED:
1391  case H_CONNECTED:
1392  /* PUT gets permanently disconnected */
1393  s->put.state = H_DISCONNECTED;
1395  break;
1396 
1397  default:
1398  GNUNET_break(0);
1399  break;
1400  }
1401  }
1402  else if (GNUNET_NO == put_request)
1403  {
1404  /* Clean up a GET request */
1405  s->get.easyhandle = NULL;
1406  s->get.s = NULL;
1407 
1408  /* If we are emulating an XHR client we need to make another GET
1409  * request.
1410  */
1411  if (GNUNET_YES == plugin->emulate_xhr)
1412  {
1415  }
1416  else
1417  {
1418  /* GET request was terminated, so disconnect session */
1420  }
1421  }
1422  else
1423  GNUNET_break(0); /* Must not happen */
1424 
1425  GNUNET_STATISTICS_set(plugin->env->stats,
1427  plugin->cur_requests,
1428  GNUNET_NO);
1429  }
1430  }
1431  while (mret == CURLM_CALL_MULTI_PERFORM);
1432  client_schedule(plugin, GNUNET_NO);
1433 }
1434 
1435 
1436 #ifdef TCP_STEALTH
1437 
1445 static curl_socket_t
1446 open_tcp_stealth_socket_cb(void *clientp,
1447  curlsocktype purpose,
1448  struct curl_sockaddr *address)
1449 {
1450  struct GNUNET_ATS_Session *s = clientp;
1451  int ret;
1452 
1453  switch (purpose)
1454  {
1455  case CURLSOCKTYPE_IPCXN:
1456  ret = socket(address->family,
1457  address->socktype,
1458  address->protocol);
1459  if (-1 == ret)
1460  return CURL_SOCKET_BAD;
1461  if (((SOCK_STREAM != address->socktype) ||
1462  ((0 != address->protocol) &&
1463  (IPPROTO_TCP != address->protocol))))
1464  return (curl_socket_t)ret;
1465  if ((0 != setsockopt(ret,
1466  IPPROTO_TCP,
1467  TCP_STEALTH,
1468  &s->address->peer,
1469  sizeof(struct GNUNET_PeerIdentity))))
1470  {
1472  _("TCP_STEALTH not supported on this platform.\n"));
1473  (void)close(ret);
1474  return CURL_SOCKET_BAD;
1475  }
1476  return (curl_socket_t)ret;
1477 
1478  case CURLSOCKTYPE_ACCEPT:
1479  GNUNET_break(0);
1480  return CURL_SOCKET_BAD;
1481  break;
1482 
1483  case CURLSOCKTYPE_LAST:
1484  GNUNET_break(0);
1485  return CURL_SOCKET_BAD;
1486 
1487  default:
1488  GNUNET_break(0);
1489  return CURL_SOCKET_BAD;
1490  }
1491 }
1492 #endif
1493 
1494 
1501 static int
1503 {
1504  CURLMcode mret;
1505  struct HttpAddress *ha;
1506  uint32_t options;
1507 
1508  ha = (struct HttpAddress *)s->address->address;
1509  options = ntohl(ha->options);
1510  /* create get request */
1511  s->get.easyhandle = curl_easy_init();
1512  s->get.s = s;
1513  if (0 != (options & HTTP_OPTIONS_TCP_STEALTH))
1514  {
1515 #ifdef TCP_STEALTH
1516  curl_easy_setopt(s->get.easyhandle,
1517  CURLOPT_OPENSOCKETFUNCTION,
1518  &open_tcp_stealth_socket_cb);
1519  curl_easy_setopt(s->get.easyhandle,
1520  CURLOPT_OPENSOCKETDATA,
1521  s);
1522 #else
1524  "Cannot connect, TCP STEALTH needed and not supported by kernel.\n");
1525  curl_easy_cleanup(s->get.easyhandle);
1526  s->get.easyhandle = NULL;
1527  s->get.s = NULL;
1528  return GNUNET_SYSERR;
1529 #endif
1530  }
1531 
1532 #if VERBOSE_CURL
1533  curl_easy_setopt(s->get.easyhandle,
1534  CURLOPT_VERBOSE,
1535  1L);
1536  curl_easy_setopt(s->get.easyhandle,
1537  CURLOPT_DEBUGFUNCTION,
1538  &client_log);
1539  curl_easy_setopt(s->get.easyhandle,
1540  CURLOPT_DEBUGDATA,
1541  &s->get);
1542 #endif
1543 #if BUILD_HTTPS
1544  curl_easy_setopt(s->get.easyhandle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
1545  {
1547  (options & HTTP_OPTIONS_VERIFY_CERTIFICATE))
1548  {
1549  curl_easy_setopt(s->get.easyhandle,
1550  CURLOPT_SSL_VERIFYPEER, 1L);
1551  curl_easy_setopt(s->get.easyhandle,
1552  CURLOPT_SSL_VERIFYHOST,
1553  2L);
1554  }
1555  else
1556  {
1557  curl_easy_setopt(s->get.easyhandle,
1558  CURLOPT_SSL_VERIFYPEER,
1559  0L);
1560  curl_easy_setopt(s->get.easyhandle,
1561  CURLOPT_SSL_VERIFYHOST,
1562  0L);
1563  }
1564  }
1565  curl_easy_setopt(s->get.easyhandle,
1566  CURLOPT_PROTOCOLS,
1567  CURLPROTO_HTTPS);
1568  curl_easy_setopt(s->get.easyhandle,
1569  CURLOPT_REDIR_PROTOCOLS,
1570  CURLPROTO_HTTPS);
1571 #else
1572  curl_easy_setopt(s->get.easyhandle,
1573  CURLOPT_PROTOCOLS,
1574  CURLPROTO_HTTP);
1575  curl_easy_setopt(s->get.easyhandle,
1576  CURLOPT_REDIR_PROTOCOLS,
1577  CURLPROTO_HTTP);
1578 #endif
1579 
1580  if (NULL != s->plugin->proxy_hostname)
1581  {
1582  curl_easy_setopt(s->get.easyhandle,
1583  CURLOPT_PROXY,
1584  s->plugin->proxy_hostname);
1585  curl_easy_setopt(s->get.easyhandle,
1586  CURLOPT_PROXYTYPE,
1587  s->plugin->proxytype);
1588  if (NULL != s->plugin->proxy_username)
1589  curl_easy_setopt(s->get.easyhandle,
1590  CURLOPT_PROXYUSERNAME,
1591  s->plugin->proxy_username);
1592  if (NULL != s->plugin->proxy_password)
1593  curl_easy_setopt(s->get.easyhandle,
1594  CURLOPT_PROXYPASSWORD,
1595  s->plugin->proxy_password);
1596  if (GNUNET_YES == s->plugin->proxy_use_httpproxytunnel)
1597  curl_easy_setopt(s->get.easyhandle,
1598  CURLOPT_HTTPPROXYTUNNEL,
1599  s->plugin->proxy_use_httpproxytunnel);
1600  }
1601 
1602  if (GNUNET_YES == s->plugin->emulate_xhr)
1603  {
1604  char *url;
1605 
1606  GNUNET_asprintf(&url,
1607  "%s,1",
1608  s->url);
1609  curl_easy_setopt(s->get.easyhandle,
1610  CURLOPT_URL,
1611  url);
1612  GNUNET_free(url);
1613  }
1614  else
1615  {
1616  curl_easy_setopt(s->get.easyhandle,
1617  CURLOPT_URL,
1618  s->url);
1619  }
1620  curl_easy_setopt(s->get.easyhandle,
1621  CURLOPT_READFUNCTION,
1622  &client_send_cb);
1623  curl_easy_setopt(s->get.easyhandle,
1624  CURLOPT_READDATA,
1625  s);
1626  curl_easy_setopt(s->get.easyhandle,
1627  CURLOPT_WRITEFUNCTION,
1628  &client_receive);
1629  curl_easy_setopt(s->get.easyhandle,
1630  CURLOPT_WRITEDATA,
1631  s);
1632  /* No timeout by default, timeout done with session timeout */
1633  curl_easy_setopt(s->get.easyhandle,
1634  CURLOPT_TIMEOUT,
1635  0L);
1636  curl_easy_setopt(s->get.easyhandle,
1637  CURLOPT_PRIVATE, s);
1638  curl_easy_setopt(s->get.easyhandle,
1639  CURLOPT_CONNECTTIMEOUT_MS,
1640  (long)(HTTP_CLIENT_NOT_VALIDATED_TIMEOUT.rel_value_us / 1000LL));
1641  curl_easy_setopt(s->get.easyhandle, CURLOPT_BUFFERSIZE,
1643 #if CURL_TCP_NODELAY
1644  curl_easy_setopt(ps->recv_endpoint,
1645  CURLOPT_TCP_NODELAY,
1646  1L);
1647 #endif
1648  curl_easy_setopt(s->get.easyhandle,
1649  CURLOPT_FOLLOWLOCATION,
1650  0L);
1651 
1652  mret = curl_multi_add_handle(s->plugin->curl_multi_handle,
1653  s->get.easyhandle);
1654  if (CURLM_OK != mret)
1655  {
1657  "Session %p : Failed to add GET handle to multihandle: `%s'\n",
1658  s,
1659  curl_multi_strerror(mret));
1660  curl_easy_cleanup(s->get.easyhandle);
1661  s->get.easyhandle = NULL;
1662  s->get.s = NULL;
1663  GNUNET_break(0);
1664  return GNUNET_SYSERR;
1665  }
1666  s->plugin->cur_requests++;
1668  "GET request `%s' established, number of requests increased to %u\n",
1669  s->url,
1670  s->plugin->cur_requests);
1671  return GNUNET_OK;
1672 }
1673 
1674 
1681 static int
1683 {
1684  CURLMcode mret;
1685  struct HttpAddress *ha;
1686  uint32_t options;
1687 
1688  ha = (struct HttpAddress *)s->address->address;
1689  options = ntohl(ha->options);
1690  /* create put request */
1692  "Session %p: Init PUT handle\n",
1693  s);
1694  s->put.easyhandle = curl_easy_init();
1695  s->put.s = s;
1696 #if VERBOSE_CURL
1697  curl_easy_setopt(s->put.easyhandle,
1698  CURLOPT_VERBOSE,
1699  1L);
1700  curl_easy_setopt(s->put.easyhandle,
1701  CURLOPT_DEBUGFUNCTION,
1702  &client_log);
1703  curl_easy_setopt(s->put.easyhandle,
1704  CURLOPT_DEBUGDATA,
1705  &s->put);
1706 #endif
1707  if (0 != (options & HTTP_OPTIONS_TCP_STEALTH))
1708  {
1709 #ifdef TCP_STEALTH
1710  curl_easy_setopt(s->put.easyhandle,
1711  CURLOPT_OPENSOCKETFUNCTION,
1712  &open_tcp_stealth_socket_cb);
1713  curl_easy_setopt(s->put.easyhandle,
1714  CURLOPT_OPENSOCKETDATA,
1715  s);
1716 #else
1718  "Cannot connect, TCP STEALTH needed and not supported by kernel.\n");
1719  curl_easy_cleanup(s->put.easyhandle);
1720  s->put.easyhandle = NULL;
1721  s->put.s = NULL;
1722  s->put.state = H_DISCONNECTED;
1723  return GNUNET_SYSERR;
1724 #endif
1725  }
1726 #if BUILD_HTTPS
1727  curl_easy_setopt(s->put.easyhandle,
1728  CURLOPT_SSLVERSION,
1729  CURL_SSLVERSION_TLSv1);
1730  {
1731  struct HttpAddress *ha;
1732  ha = (struct HttpAddress *)s->address->address;
1733 
1736  {
1737  curl_easy_setopt(s->put.easyhandle,
1738  CURLOPT_SSL_VERIFYPEER,
1739  1L);
1740  curl_easy_setopt(s->put.easyhandle,
1741  CURLOPT_SSL_VERIFYHOST,
1742  2L);
1743  }
1744  else
1745  {
1746  curl_easy_setopt(s->put.easyhandle,
1747  CURLOPT_SSL_VERIFYPEER,
1748  0L);
1749  curl_easy_setopt(s->put.easyhandle,
1750  CURLOPT_SSL_VERIFYHOST,
1751  0L);
1752  }
1753  }
1754  curl_easy_setopt(s->put.easyhandle,
1755  CURLOPT_PROTOCOLS,
1756  CURLPROTO_HTTPS);
1757  curl_easy_setopt(s->put.easyhandle,
1758  CURLOPT_REDIR_PROTOCOLS,
1759  CURLPROTO_HTTPS);
1760 #else
1761  curl_easy_setopt(s->put.easyhandle,
1762  CURLOPT_PROTOCOLS,
1763  CURLPROTO_HTTP);
1764  curl_easy_setopt(s->put.easyhandle,
1765  CURLOPT_REDIR_PROTOCOLS,
1766  CURLPROTO_HTTP);
1767 #endif
1768  if (NULL != s->plugin->proxy_hostname)
1769  {
1770  curl_easy_setopt(s->put.easyhandle,
1771  CURLOPT_PROXY,
1772  s->plugin->proxy_hostname);
1773  curl_easy_setopt(s->put.easyhandle,
1774  CURLOPT_PROXYTYPE,
1775  s->plugin->proxytype);
1776  if (NULL != s->plugin->proxy_username)
1777  curl_easy_setopt(s->put.easyhandle,
1778  CURLOPT_PROXYUSERNAME,
1779  s->plugin->proxy_username);
1780  if (NULL != s->plugin->proxy_password)
1781  curl_easy_setopt(s->put.easyhandle,
1782  CURLOPT_PROXYPASSWORD,
1783  s->plugin->proxy_password);
1784  if (GNUNET_YES == s->plugin->proxy_use_httpproxytunnel)
1785  curl_easy_setopt(s->put.easyhandle,
1786  CURLOPT_HTTPPROXYTUNNEL,
1787  s->plugin->proxy_use_httpproxytunnel);
1788  }
1789 
1790  curl_easy_setopt(s->put.easyhandle,
1791  CURLOPT_URL,
1792  s->url);
1793  curl_easy_setopt(s->put.easyhandle,
1794  CURLOPT_UPLOAD,
1795  1L);
1796  curl_easy_setopt(s->put.easyhandle,
1797  CURLOPT_READFUNCTION,
1798  &client_send_cb);
1799  curl_easy_setopt(s->put.easyhandle,
1800  CURLOPT_READDATA,
1801  s);
1802  curl_easy_setopt(s->put.easyhandle,
1803  CURLOPT_WRITEFUNCTION,
1805  curl_easy_setopt(s->put.easyhandle,
1806  CURLOPT_WRITEDATA,
1807  s);
1808  /* No timeout by default, timeout done with session timeout */
1809  curl_easy_setopt(s->put.easyhandle,
1810  CURLOPT_TIMEOUT,
1811  0L);
1812  curl_easy_setopt(s->put.easyhandle,
1813  CURLOPT_PRIVATE,
1814  s);
1815  curl_easy_setopt(s->put.easyhandle,
1816  CURLOPT_CONNECTTIMEOUT_MS,
1817  (long)(HTTP_CLIENT_NOT_VALIDATED_TIMEOUT.rel_value_us / 1000LL));
1818  curl_easy_setopt(s->put.easyhandle, CURLOPT_BUFFERSIZE,
1820 #if CURL_TCP_NODELAY
1821  curl_easy_setopt(s->put.easyhandle, CURLOPT_TCP_NODELAY, 1);
1822 #endif
1823  mret = curl_multi_add_handle(s->plugin->curl_multi_handle,
1824  s->put.easyhandle);
1825  if (CURLM_OK != mret)
1826  {
1828  "Session %p : Failed to add PUT handle to multihandle: `%s'\n",
1829  s, curl_multi_strerror(mret));
1830  curl_easy_cleanup(s->put.easyhandle);
1831  s->put.easyhandle = NULL;
1832  s->put.s = NULL;
1833  s->put.state = H_DISCONNECTED;
1834  return GNUNET_SYSERR;
1835  }
1836  s->put.state = H_CONNECTED;
1837  s->plugin->cur_requests++;
1838 
1840  "PUT request `%s' established, number of requests increased to %u\n",
1841  s->url, s->plugin->cur_requests);
1842 
1843  return GNUNET_OK;
1844 }
1845 
1846 
1853 static int
1855 {
1856  struct HTTP_Client_Plugin *plugin = s->plugin;
1857  int res = GNUNET_OK;
1858 
1859  /* create url */
1860  if (NULL ==
1862  s->address->address,
1863  s->address->address_length))
1864  {
1866  "Invalid address peer `%s'\n",
1867  GNUNET_i2s(&s->address->peer));
1868  return GNUNET_SYSERR;
1869  }
1870 
1871  GNUNET_asprintf(&s->url,
1872  "%s/%s;%u",
1874  s->address->address,
1875  s->address->address_length),
1876  GNUNET_i2s_full(plugin->env->my_identity),
1877  plugin->last_tag);
1878 
1879  plugin->last_tag++;
1881  "Initiating outbound session peer `%s' using address `%s'\n",
1882  GNUNET_i2s(&s->address->peer), s->url);
1883 
1885  return GNUNET_SYSERR;
1886  /* If we are emulating an XHR client then delay sending a PUT request until
1887  * there is something to send.
1888  */
1889  if (GNUNET_YES == plugin->emulate_xhr)
1890  {
1892  }
1893  else if (GNUNET_SYSERR == client_connect_put(s))
1894  return GNUNET_SYSERR;
1895 
1897  "Session %p: connected with GET %p and PUT %p\n",
1898  s, s->get.easyhandle,
1899  s->put.easyhandle);
1900  /* Perform connect */
1901  GNUNET_STATISTICS_set(plugin->env->stats,
1903  plugin->cur_requests,
1904  GNUNET_NO);
1905  /* Re-schedule since handles have changed */
1906  if (NULL != plugin->client_perform_task)
1907  {
1909  plugin->client_perform_task = NULL;
1910  }
1911 
1912  /* Schedule task to run immediately */
1914  plugin);
1915  return res;
1916 }
1917 
1918 
1926 static enum GNUNET_NetworkType
1928  struct GNUNET_ATS_Session *session)
1929 {
1930  return session->scope;
1931 }
1932 
1933 
1941 static enum GNUNET_NetworkType
1943  const struct GNUNET_HELLO_Address *address)
1944 {
1945  struct HTTP_Client_Plugin *plugin = cls;
1946 
1948  address);
1949 }
1950 
1951 
1957 static void
1959 {
1960  struct GNUNET_ATS_Session *s = cls;
1961  struct GNUNET_TIME_Relative left;
1962 
1963  s->timeout_task = NULL;
1965  if (0 != left.rel_value_us)
1966  {
1967  /* not actually our turn yet, but let's at least update
1968  the monitor, it may think we're about to die ... */
1970  s,
1974  s);
1975  return;
1976  }
1977  LOG(TIMEOUT_LOG,
1978  "Session %p was idle for %s, disconnecting\n",
1979  s,
1981  GNUNET_YES));
1984  s));
1985 }
1986 
1987 
1996 static struct GNUNET_ATS_Session *
1998  const struct GNUNET_HELLO_Address *address)
1999 {
2000  struct HTTP_Client_Plugin *plugin = cls;
2001  struct GNUNET_ATS_Session *s;
2002  struct sockaddr *sa;
2003  enum GNUNET_NetworkType net_type;
2004  size_t salen = 0;
2005  int res;
2006 
2007  GNUNET_assert(NULL != address->address);
2008 
2009  /* find existing session */
2010  s = client_lookup_session(plugin, address);
2011  if (NULL != s)
2012  return s;
2013 
2014  /* create a new session */
2015  if (plugin->max_requests <= plugin->cur_requests)
2016  {
2018  "Maximum number of requests (%u) reached: "
2019  "cannot connect to peer `%s'\n",
2020  plugin->max_requests,
2021  GNUNET_i2s(&address->peer));
2022  return NULL;
2023  }
2024 
2025  /* Determine network location */
2026  net_type = GNUNET_NT_UNSPECIFIED;
2028  address->address_length,
2029  &res);
2030  if (GNUNET_SYSERR == res)
2031  return NULL;
2032  if (GNUNET_YES == res)
2033  {
2034  GNUNET_assert(NULL != sa);
2035  if (AF_INET == sa->sa_family)
2036  {
2037  salen = sizeof(struct sockaddr_in);
2038  }
2039  else if (AF_INET6 == sa->sa_family)
2040  {
2041  salen = sizeof(struct sockaddr_in6);
2042  }
2043  net_type = plugin->env->get_address_type(plugin->env->cls, sa, salen);
2044  GNUNET_free(sa);
2045  }
2046  else if (GNUNET_NO == res)
2047  {
2048  /* Cannot convert to sockaddr -> is external hostname */
2049  net_type = GNUNET_NT_WAN;
2050  }
2051  if (GNUNET_NT_UNSPECIFIED == net_type)
2052  {
2053  GNUNET_break(0);
2054  return NULL;
2055  }
2056 
2057  s = GNUNET_new(struct GNUNET_ATS_Session);
2058  s->plugin = plugin;
2059  s->address = GNUNET_HELLO_address_copy(address);
2060  s->scope = net_type;
2061 
2062  s->put.state = H_NOT_CONNECTED;
2066  s);
2068  "Created new session %p for `%s' address `%s''\n",
2069  s,
2071  s->address->address,
2072  s->address->address_length),
2073  GNUNET_i2s(&s->address->peer));
2074 
2075  /* add new session */
2077  &s->address->peer,
2078  s,
2080  /* initiate new connection */
2081  if (GNUNET_SYSERR == client_connect(s))
2082  {
2084  "Cannot connect to peer `%s' address `%s''\n",
2087  GNUNET_i2s(&s->address->peer));
2089  return NULL;
2090  }
2091  notify_session_monitor(plugin,
2092  s,
2094  notify_session_monitor(plugin,
2095  s,
2096  GNUNET_TRANSPORT_SS_UP); /* or handshake? */
2097  return s;
2098 }
2099 
2100 
2107 static int
2109 {
2110  curl_global_init(CURL_GLOBAL_ALL);
2111  plugin->curl_multi_handle = curl_multi_init();
2112 
2113  if (NULL == plugin->curl_multi_handle)
2114  {
2116  _("Could not initialize curl multi handle, failed to start %s plugin!\n"),
2117  plugin->name);
2118  return GNUNET_SYSERR;
2119  }
2120  return GNUNET_OK;
2121 }
2122 
2123 
2136 static int
2138  const void *addr,
2139  size_t addrlen)
2140 {
2141  /* A HTTP/S client does not have any valid address so:*/
2142  return GNUNET_NO;
2143 }
2144 
2145 
2152 void *
2154 {
2155  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2156  struct HTTP_Client_Plugin *plugin = api->cls;
2157 
2158  if (NULL == api->cls)
2159  {
2160  /* Stub shutdown */
2161  GNUNET_free(api);
2162  return NULL;
2163  }
2165  _("Shutting down plugin `%s'\n"),
2166  plugin->name);
2169  plugin);
2170  if (NULL != plugin->client_perform_task)
2171  {
2173  plugin->client_perform_task = NULL;
2174  }
2175  if (NULL != plugin->curl_multi_handle)
2176  {
2177  curl_multi_cleanup(plugin->curl_multi_handle);
2178  plugin->curl_multi_handle = NULL;
2179  }
2180  curl_global_cleanup();
2182  _("Shutdown for plugin `%s' complete\n"),
2183  plugin->name);
2188  GNUNET_free(plugin);
2189  GNUNET_free(api);
2190  return NULL;
2191 }
2192 
2193 
2200 static int
2202 {
2203  unsigned long long max_requests;
2204  char *proxy_type;
2205 
2206  /* Optional parameters */
2207  if (GNUNET_OK !=
2209  plugin->name,
2210  "MAX_CONNECTIONS",
2211  &max_requests))
2212  max_requests = 128;
2213  plugin->max_requests = max_requests;
2214 
2216  _("Maximum number of requests is %u\n"),
2217  plugin->max_requests);
2218 
2219  /* Read proxy configuration */
2220  if (GNUNET_OK ==
2222  plugin->name,
2223  "PROXY",
2224  &plugin->proxy_hostname))
2225  {
2227  "Found proxy host: `%s'\n",
2228  plugin->proxy_hostname);
2229  /* proxy username */
2230  if (GNUNET_OK ==
2232  plugin->name,
2233  "PROXY_USERNAME",
2234  &plugin->proxy_username))
2235  {
2237  "Found proxy username name: `%s'\n",
2238  plugin->proxy_username);
2239  }
2240 
2241  /* proxy password */
2242  if (GNUNET_OK ==
2244  plugin->name,
2245  "PROXY_PASSWORD",
2246  &plugin->proxy_password))
2247  {
2249  "Found proxy password name: `%s'\n",
2250  plugin->proxy_password);
2251  }
2252 
2253  /* proxy type */
2254  if (GNUNET_OK ==
2256  plugin->name,
2257  "PROXY_TYPE",
2258  &proxy_type))
2259  {
2260  GNUNET_STRINGS_utf8_toupper(proxy_type, proxy_type);
2261 
2262  if (0 == strcmp(proxy_type, "HTTP"))
2263  plugin->proxytype = CURLPROXY_HTTP;
2264  else if (0 == strcmp(proxy_type, "SOCKS4"))
2265  plugin->proxytype = CURLPROXY_SOCKS4;
2266  else if (0 == strcmp(proxy_type, "SOCKS5"))
2267  plugin->proxytype = CURLPROXY_SOCKS5;
2268  else if (0 == strcmp(proxy_type, "SOCKS4A"))
2269  plugin->proxytype = CURLPROXY_SOCKS4A;
2270  else if (0 == strcmp(proxy_type, "SOCKS5_HOSTNAME "))
2271  plugin->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
2272  else
2273  {
2275  _("Invalid proxy type: `%s', disabling proxy! Check configuration!\n"),
2276  proxy_type);
2277 
2278  GNUNET_free(proxy_type);
2279  GNUNET_free(plugin->proxy_hostname);
2280  plugin->proxy_hostname = NULL;
2282  plugin->proxy_username = NULL;
2284  plugin->proxy_password = NULL;
2285 
2286  return GNUNET_SYSERR;
2287  }
2288 
2290  "Found proxy type: `%s'\n",
2291  proxy_type);
2292  }
2293 
2294  /* proxy http tunneling */
2297  plugin->name,
2298  "PROXY_HTTP_TUNNELING");
2301 
2302  GNUNET_free_non_null(proxy_type);
2303  }
2304 
2305  /* Should we emulate an XHR client for testing? */
2306  plugin->emulate_xhr
2308  plugin->name,
2309  "EMULATE_XHR");
2310  return GNUNET_OK;
2311 }
2312 
2313 
2322 static const char *
2324  const void *addr,
2325  size_t addrlen)
2326 {
2328  addr,
2329  addrlen);
2330 }
2331 
2332 
2342 static void
2344  const struct GNUNET_PeerIdentity *peer,
2345  struct GNUNET_ATS_Session *session)
2346 {
2348 }
2349 
2350 
2361 static void
2363  const struct GNUNET_PeerIdentity *peer,
2364  struct GNUNET_ATS_Session *s,
2365  struct GNUNET_TIME_Relative delay)
2366 {
2369  "New inbound delay %s\n",
2371  GNUNET_NO));
2372  if (s->recv_wakeup_task != NULL)
2373  {
2375  s->recv_wakeup_task
2377  &client_wake_up,
2378  s);
2379  }
2380 }
2381 
2382 
2392 static int
2394  const struct GNUNET_PeerIdentity *peer,
2395  void *value)
2396 {
2397  struct HTTP_Client_Plugin *plugin = cls;
2398  struct GNUNET_ATS_Session *session = value;
2399 
2400  notify_session_monitor(plugin,
2401  session,
2403  notify_session_monitor(plugin,
2404  session,
2405  GNUNET_TRANSPORT_SS_UP); /* FIXME: or handshake? */
2406  return GNUNET_OK;
2407 }
2408 
2409 
2422 static void
2425  void *sic_cls)
2426 {
2427  struct HTTP_Client_Plugin *plugin = cls;
2428 
2429  plugin->sic = sic;
2430  plugin->sic_cls = sic_cls;
2431  if (NULL != sic)
2432  {
2435  plugin);
2436  /* signal end of first iteration */
2437  sic(sic_cls, NULL, NULL);
2438  }
2439 }
2440 
2441 
2445 void *
2447 {
2450  struct HTTP_Client_Plugin *plugin;
2451 
2452  if (NULL == env->receive)
2453  {
2454  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
2455  initialze the plugin or the API */
2457  api->cls = NULL;
2461  return api;
2462  }
2463 
2464  plugin = GNUNET_new(struct HTTP_Client_Plugin);
2465  plugin->env = env;
2467  GNUNET_YES);
2469  api->cls = plugin;
2470  api->send = &http_client_plugin_send;
2484 #if BUILD_HTTPS
2485  plugin->name = "transport-https_client";
2486  plugin->protocol = "https";
2487 #else
2488  plugin->name = "transport-http_client";
2489  plugin->protocol = "http";
2490 #endif
2491  plugin->last_tag = 1;
2492 
2493  if (GNUNET_SYSERR == client_configure_plugin(plugin))
2494  {
2496  return NULL;
2497  }
2498 
2499  /* Start client */
2500  if (GNUNET_SYSERR == client_start(plugin))
2501  {
2503  return NULL;
2504  }
2505  return api;
2506 }
2507 
2508 /* end of plugin_transport_http_client.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static enum GNUNET_NetworkType http_client_plugin_get_network_for_address(void *cls, const struct GNUNET_HELLO_Address *address)
Function obtain the network type for an address.
size_t address_length
Number of bytes in address.
static int http_client_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
Another peer has suggested an address for this peer and transport plugin.
Session is being torn down and about to disappear.
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
uint32_t num_bytes_pending
Number of bytes pending transmission for this session.
HTTP_PUT_REQUEST_STATE
State of a HTTP PUT request.
static int client_receive_mst_cb(void *cls, const struct GNUNET_MessageHeader *message)
Callback for message stream tokenizer.
#define HTTP_CLIENT_SESSION_TIMEOUT
static unsigned int http_client_query_keepalive_factor(void *cls)
Function that is called to get the keepalive factor.
struct GNUNET_MessageStreamTokenizer * msg_tk
Message stream tokenizer for incoming data.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
static int http_client_plugin_session_disconnect(void *cls, struct GNUNET_ATS_Session *s)
Disconnect a session.
uint32_t options
Address options see enum HttpAddressOptions
GNUNET_TRANSPORT_AddressToString address_to_string
Function that will be called to convert a binary address to a string (numeric conversion only)...
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
struct GNUNET_SCHEDULER_Task * recv_wakeup_task
Task to wake up client receive handle when receiving is allowed again.
uint64_t rel_value_us
The actual value.
static int client_configure_plugin(struct HTTP_Client_Plugin *plugin)
Configure plugin.
const void * address
Binary representation of the address (plugin-specific).
char * buf
buffer containing data to send
unsigned int msgs_in_queue
Number of messages waiting for transmission to this peer.
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_SCHEDULER_Task * timeout_task
Session timeout task.
struct HTTP_Message * msg_tail
previous pointer for double linked list
curl_proxytype proxytype
Type of proxy server:
uint32_t last_tag
Last used unique HTTP connection tag.
library to make it easy to download JSON replies over HTTP
struct Plugin * plugin
Pointer to the global plugin struct.
const char * http_common_plugin_address_to_url(void *cls, const void *addr, size_t addrlen)
FIXME.
int http_common_plugin_string_to_address(void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added)
Function called to convert a string address to a binary address.
struct HTTP_Client_Plugin * plugin
Pointer to the global plugin struct.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
GNUNET_TRANSPORT_DisconnectPeerFunction disconnect_peer
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
#define PUT_DISCONNECT_TIMEOUT
GNUNET_TRANSPORT_AddressToType get_address_type
Function that will be called to figure if an address is an loopback, LAN, WAN etc.
int is_inbound
GNUNET_YES if this is an inbound connection, GNUNET_NO if this is an outbound connection, GNUNET_SYSERR if connections of this plugin are so fundamentally bidirectional that they have no &#39;initiator&#39;
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
char * proxy_username
Username for the proxy server.
enum GNUNET_TRANSPORT_SessionState state
New state of the session.
size_t pos
amount of data already sent
static int client_connect_get(struct GNUNET_ATS_Session *s)
Connect GET request.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
char * protocol
Plugin protocol http, https.
static int send_session_info_iter(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Return information about the given session to the monitor callback.
#define GNUNET_TIME_UNIT_SECONDS
One second.
GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
struct RequestHandle put
Handle for the HTTP PUT request.
Message to send using http.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
struct GNUNET_SERVER_MessageStreamTokenizer * msg_tk
Message stream tokenizer for incoming data.
GNUNET_TRANSPORT_SessionMonitorSetup setup_monitor
Function to monitor the sessions managed by the plugin.
struct HTTP_Message * next
next pointer for double linked list
static size_t client_receive_put(void *stream, size_t size, size_t nmemb, void *cls)
Callback method used with libcurl when data for a PUT request are received.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static curl_proxytype proxy_type
Proxy type we are using (can be NULL).
const struct GNUNET_PeerIdentity * my_identity
Identity of this peer.
static void client_session_timeout(void *cls)
Session was idle, so disconnect it.
struct GNUNET_TIME_Absolute timeout
When does this session time out.
static void http_client_plugin_update_session_timeout(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Session *session)
Function that will be called whenever the transport service wants to notify the plugin that a session...
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
Wide area network (i.e.
Definition: gnunet_nt_lib.h:54
static struct GNUNET_ATS_Session * http_client_plugin_get_session(void *cls, const struct GNUNET_HELLO_Address *address)
Creates a new outbound session the transport service will use to send data to the peer...
#define GNUNET_NO
Definition: gnunet_common.h:78
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void client_run(void *cls)
Task performing curl operations.
struct GNUNET_HELLO_Address * address
Address.
static void client_wake_up(void *cls)
Wake up a curl handle which was suspended.
struct GNUNET_TRANSPORT_PluginEnvironment * env
Our environment.
struct RequestHandle get
Handle for the HTTP GET request.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
struct HTTP_Message * msg_head
next pointer for double linked list
struct GNUNET_SCHEDULER_Task * put_disconnect_task
Session timeout task.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
const struct GNUNET_HELLO_Address * address
Address used by the session.
unsigned long long bytes_in_queue
Number of bytes waiting for transmission to this peer.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
static int ret
Final status code.
Definition: gnunet-arm.c:89
uint64_t abs_value_us
The actual value.
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:35
uint32_t num_msg_pending
Number of messages pending transmission for this session.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
void * transmit_cont_cls
Closure for transmit_cont.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
void GNUNET_NETWORK_fdset_copy_native(struct GNUNET_NETWORK_FDSet *to, const fd_set *from, int nfds)
Copy a native fd set into the GNUnet representation.
Definition: network.c:1108
struct GNUNET_TIME_Absolute receive_delay
Until when does this plugin refuse to receive to manage staying within the inbound quota...
The request handle.
GNUNET_TRANSPORT_TransmitContinuation transmit_cont
Continuation function to call once the transmission buffer has again space available.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
int proxy_use_httpproxytunnel
Use proxy tunneling: Tunnel all operations through a given HTTP instead of have the proxy evaluate th...
GNUNET_TRANSPORT_SessionEnd session_end
Function that must be called by the plugin when a non-NULL session handle stops being valid (is destr...
Paused, nothing to send.
GNUNET_TRANSPORT_PluginReceiveCallback receive
Function that should be called by the transport plugin whenever a message is received.
struct GNUNET_TIME_Absolute next_receive
Absolute time when to receive data again Used for receive throttling.
GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout
Function that will be called whenever the transport service wants to notify the plugin that a session...
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1254
static struct GNUNET_ATS_SolverFunctions * plugin
Our solver.
const struct GNUNET_HELLO_Address * address
Address we are looking for.
Information about a plugin&#39;s session.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:130
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1237
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1238
static void notify_session_monitor(struct HTTP_Client_Plugin *plugin, struct GNUNET_ATS_Session *session, enum GNUNET_TRANSPORT_SessionState state)
If a session monitor is attached, notify it about the new session state.
void GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
Convert the utf-8 input string to upper case.
Definition: strings.c:577
void * cls
Closure for the various callbacks.
enum State state
current state of profiling
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
void * cls
Closure for all of the callbacks.
static void client_put_disconnect(void *cls)
When we have nothing to transmit, we pause the HTTP PUT after a while (so that gnurl stops asking)...
Temporarily disconnected.
#define LIBGNUNET_PLUGIN_TRANSPORT_INIT
static char * value
Value of the record to add/remove.
static int client_schedule(struct HTTP_Client_Plugin *plugin, int now)
Function setting up file descriptors and scheduling task to run.
GNUNET_TRANSPORT_StringToAddress string_to_address
Function that will be called to convert a string address to binary (numeric conversion only)...
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:410
static struct GNUNET_ATS_Session * client_lookup_session(struct HTTP_Client_Plugin *plugin, const struct GNUNET_HELLO_Address *address)
Check if a sessions exists for an specific address.
Information about ongoing sessions of the transport client.
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1264
The transport service will pass a pointer to a struct of this type as the first and only argument to ...
static enum GNUNET_NetworkType scope
Which network scope do we belong to?
GNUNET_TRANSPORT_GetNetworkType get_network
Function to obtain the network type for a session.
Handle to a message stream tokenizer.
Definition: mst.c:43
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:80
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:686
collection of IO descriptors
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1784
void http_common_plugin_address_pretty_printer(void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
Convert the transports address to a nice, human-readable format.
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:84
uint32_t options
My options to be included in the address.
void(* GNUNET_TRANSPORT_SessionInfoCallback)(void *cls, struct GNUNET_ATS_Session *session, const struct GNUNET_TRANSPORT_SessionInfo *info)
Function called by the plugin with information about the current sessions managed by the plugin (for ...
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:440
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:113
struct GNUNET_TIME_Absolute session_timeout
At what time will this session timeout (unless activity happens)?
static int session_lookup_client_by_address(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Locate the seession object for a given address.
static ssize_t http_client_plugin_send(void *cls, struct GNUNET_ATS_Session *s, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
Function that can be used by the transport service to transmit a message using the plugin...
Internal representation of the hash map.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
GNUNET_TRANSPORT_UpdateInboundDelay update_inbound_delay
Function that will be called whenever the transport service wants to notify the plugin that the inbou...
Closure for session_lookup_client_by_address().
static int client_connect_put(struct GNUNET_ATS_Session *s)
Connect a HTTP put request.
int state
The processing state.
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
static int destroy_session_cb(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Callback to destroys all sessions on exit.
static int res
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static enum GNUNET_NetworkType http_client_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
Function obtain the network type for a session.
static void client_reschedule_session_timeout(struct GNUNET_ATS_Session *s)
Increment session timeout due to activity for session s.
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
static CURL * curl
Current CURL handle.
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.
static int client_connect(struct GNUNET_ATS_Session *s)
Connect both PUT and GET request for a session.
size_t size
buffer length
struct GNUNET_CONTAINER_MultiPeerMap * sessions
Open sessions.
static const char * http_client_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
Function to convert an address to a human-readable string.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
char * url
The URL to connect to.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
#define HTTP_CLIENT_NOT_VALIDATED_TIMEOUT
static size_t client_receive(void *stream, size_t size, size_t nmemb, void *cls)
Callback method used with libcurl when data for a GET request are received.
int emulate_xhr
Should we emulate an XHR client for testing?
enum GNUNET_NetworkType scope
ATS network type.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
void(* GNUNET_TRANSPORT_TransmitContinuation)(void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire)
Function called by the GNUNET_TRANSPORT_TransmitFunction upon "completion".
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static struct GNUNET_SCHEDULER_Task * timeout_task
Task to be run on timeout.
Definition: gnunet-arm.c:119
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
struct GNUNET_PeerIdentity peer
For which peer is this an address?
Just created, not yet connected.
static void http_client_plugin_peer_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
Enable TCP Stealth-style port knocking.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
void * sic_cls
Closure for sic.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
#define LIBGNUNET_PLUGIN_TRANSPORT_DONE
Encapsulation of all of the state of the plugin.
Allow multiple values with the same key.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don&#39;t receive messages from the peer...
const char * http_common_plugin_address_to_string(const char *plugin, const void *addr, size_t addrlen)
Function called for a quick conversion of the binary address to a numeric address.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
This is just an update about the session, the state did not change.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_NetworkType http_common_get_network_for_address(struct GNUNET_TRANSPORT_PluginEnvironment *env, const struct GNUNET_HELLO_Address *address)
Function obtain the network type for an address.
GNUNET_TRANSPORT_QueryKeepaliveFactorFunction query_keepalive_factor
Function that is used to query keepalive factor.
The identity of the host (wraps the signing key of the peer).
static void http_client_plugin_setup_monitor(void *cls, GNUNET_TRANSPORT_SessionInfoCallback sic, void *sic_cls)
Begin monitoring sessions of a plugin.
struct sockaddr * http_common_socket_from_address(const void *addr, size_t addrlen, int *res)
Create a socketaddr from a HTTP address.
struct GNUNET_SCHEDULER_Task * client_perform_task
curl perform task
unsigned int cur_requests
Current number of sockets the plugin can use Each http connections are two requests.
#define HTTP_STAT_STR_CONNECTIONS
struct GNUNET_PeerIdentity target
To whom are we talking to.
CURLM * curl_multi_handle
cURL Multihandle
#define PLUGIN_NAME
An address for communicating with a peer.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:109
struct GNUNET_STATISTICS_Handle * stats
Handle for reporting statistics.
struct GNUNET_ATS_Session * ret
Session that was found.
#define GNUNET_log(kind,...)
The session was created (first call for each session object).
Entry in list of pending tasks.
Definition: scheduler.c:131
static int client_start(struct HTTP_Client_Plugin *plugin)
Setup http_client plugin.
struct HTTP_Message * prev
previous pointer for double linked list
unsigned int max_requests
Maximum number of sockets the plugin can use Each http connections are two requests.
size_t overhead
Outbound overhead due to HTTP connection Add to next message of this session when calling callback...
Verify X509 server certificate, it should be valid.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
GNUNET_TRANSPORT_AddressPrettyPrinter address_pretty_printer
Function to pretty-print addresses.
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
char * proxy_hostname
Proxy configuration: hostname or ip of the proxy server.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition: time.c:353
#define LOG(kind,...)
Temporary disconnect in progress due to inactivity.
struct GNUNET_ATS_Session * s
The related session.
Run with the default priority (normal P2P operations).
GNUNET_TRANSPORT_CheckAddress check_address
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
GNUNET_TRANSPORT_SessionState
Possible states of a session in a plugin.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
uint32_t data
The data value.
static void http_client_plugin_update_inbound_delay(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Session *s, struct GNUNET_TIME_Relative delay)
Function that will be called whenever the transport service wants to notify the plugin that the inbou...
static char * address
GNS address for this phone.
CURL * easyhandle
The curl easy handle.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_HELLO_address_free(addr)
Free an address.
HTTP addresses including a full URI.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
#define TIMEOUT_LOG
#define GNUNET_malloc(size)
Wrapper around malloc.
char * proxy_password
Password for the proxy server.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
Send request while temporary disconnect, reconnect.
GNUNET_TRANSPORT_GetNetworkTypeForAddress get_network_for_address
Function to obtain the network type for an address.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
Category of last resort.
Definition: gnunet_nt_lib.h:39
static size_t client_send_cb(void *stream, size_t size, size_t nmemb, void *cls)
Callback method used with libcurl Method is called when libcurl needs to read data during sending...
static void client_delete_session(struct GNUNET_ATS_Session *s)
Delete session s.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956