GNUnet  0.10.x
plugin_transport_udp.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2010-2017 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 #include "platform.h"
29 #include "plugin_transport_udp.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_util_lib.h"
33 #include "gnunet_nat_service.h"
34 #include "gnunet_protocols.h"
36 #include "gnunet_signatures.h"
37 #include "gnunet_constants.h"
41 #include "transport.h"
42 
43 #define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__)
44 
48 #define UDP_SESSION_TIME_OUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
49 
58 #define UDP_MAX_MESSAGES_IN_DEFRAG 3
59 
67 #define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128
68 
69 
73 struct UDPMessage
74 {
79 
83  uint32_t reserved;
84 
89 
90 };
91 
92 
97 {
101  struct PrettyPrinterContext *next;
102 
106  struct PrettyPrinterContext *prev;
107 
111  struct Plugin *plugin;
112 
116  struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
117 
122 
126  void *asc_cls;
127 
132 
136  int ipv6;
137 
141  uint32_t options;
142 
146  uint16_t port;
147 
148 };
149 
150 
154 struct GNUNET_ATS_Session
155 {
159  struct GNUNET_PeerIdentity target;
160 
165 
169  struct Plugin *plugin;
170 
175 
179  struct GNUNET_TIME_Relative flow_delay_for_other_peer;
180 
186  struct GNUNET_TIME_Relative flow_delay_from_other_peer;
187 
192 
197 
201  struct GNUNET_TIME_Absolute last_transmit_time;
202 
206  struct GNUNET_TIME_Relative last_expected_ack_delay;
207 
211  struct GNUNET_TIME_Relative last_expected_msg_delay;
212 
217 
221  unsigned long long bytes_in_queue;
222 
226  unsigned int msgs_in_queue;
227 
234  unsigned int rc;
235 
240 
248 };
249 
250 
251 
257 {
258 
263 
267  struct Plugin *plugin;
268 
273 
278  const union UdpAddress *udp_addr;
279 
285  struct GNUNET_PeerIdentity sender;
286 
290  size_t udp_addr_len;
291 
295  enum GNUNET_NetworkType network_type;
296 
301 };
302 
303 
308 {
313 
318 
322  struct Plugin *plugin;
323 
328 
333 
338 
342  void *cont_cls;
343 
348 
354  struct GNUNET_TIME_Absolute next_frag_time;
355 
361  struct GNUNET_TIME_Relative flow_delay_from_other_peer;
362 
367 
371  size_t payload_size;
372 
376  size_t on_wire_size;
377 
378 };
379 
380 
391 typedef void
392 (*QueueContinuation) (void *cls,
393  struct UDP_MessageWrapper *udpw,
394  int result);
395 
396 
401 {
406 
411 
416 
420  char *msg_buf;
421 
427 
431  void *qc_cls;
432 
439 
443  void *cont_cls;
444 
451 
456 
461  struct GNUNET_TIME_Absolute transmission_time;
462 
467 
471  size_t msg_size;
472 
476  size_t payload_size;
477 
478 };
479 
480 
482 
487 {
492 
499 
503  struct GNUNET_PeerIdentity sender;
504 
505 };
506 
508 
509 
510 /* ************************* Monitoring *********** */
511 
512 
521 static void
523  struct GNUNET_ATS_Session *session,
525 {
526  struct GNUNET_TRANSPORT_SessionInfo info;
527 
528  if (NULL == plugin->sic)
529  return;
530  if (GNUNET_YES == session->in_destroy)
531  return; /* already destroyed, just RC>0 left-over actions */
532  memset (&info,
533  0,
534  sizeof (info));
535  info.state = state;
536  info.is_inbound = GNUNET_SYSERR; /* hard to say */
537  info.num_msg_pending = session->msgs_in_queue;
538  info.num_bytes_pending = session->bytes_in_queue;
539  /* info.receive_delay remains zero as this is not supported by UDP
540  (cannot selectively not receive from 'some' peer while continuing
541  to receive from others) */
542  info.session_timeout = session->timeout;
543  info.address = session->address;
544  plugin->sic (plugin->sic_cls,
545  session,
546  &info);
547 }
548 
549 
558 static int
560  const struct GNUNET_PeerIdentity *peer,
561  void *value)
562 {
563  struct Plugin *plugin = cls;
564  struct GNUNET_ATS_Session *session = value;
565 
566  notify_session_monitor (plugin,
567  session,
569  notify_session_monitor (plugin,
570  session,
572  return GNUNET_OK;
573 }
574 
575 
588 static void
591  void *sic_cls)
592 {
593  struct Plugin *plugin = cls;
594 
595  plugin->sic = sic;
596  plugin->sic_cls = sic_cls;
597  if (NULL != sic)
598  {
601  plugin);
602  /* signal end of first iteration */
603  sic (sic_cls,
604  NULL,
605  NULL);
606  }
607 }
608 
609 
610 /* ****************** Little Helpers ****************** */
611 
612 
618 static void
620 {
621  if (NULL != s->address)
622  {
624  s->address = NULL;
625  }
626  if (NULL != s->frag_ctx)
627  {
629  NULL,
630  NULL);
631  GNUNET_free (s->frag_ctx);
632  s->frag_ctx = NULL;
633  }
634  if (NULL != s->mst)
635  {
636  GNUNET_MST_destroy (s->mst);
637  s->mst = NULL;
638  }
639  GNUNET_free (s);
640 }
641 
642 
651 static unsigned int
653 {
654  return 15;
655 }
656 
657 
665 static enum GNUNET_NetworkType
667  struct GNUNET_ATS_Session *session)
668 {
669  return session->scope;
670 }
671 
672 
680 static enum GNUNET_NetworkType
682  const struct GNUNET_HELLO_Address *address)
683 {
684  struct Plugin *plugin = cls;
685  size_t addrlen;
686  struct sockaddr_in a4;
687  struct sockaddr_in6 a6;
688  const struct IPv4UdpAddress *u4;
689  const struct IPv6UdpAddress *u6;
690  const void *sb;
691  size_t sbs;
692 
693  addrlen = address->address_length;
694  if (addrlen == sizeof(struct IPv6UdpAddress))
695  {
696  GNUNET_assert (NULL != address->address); /* make static analysis happy */
697  u6 = address->address;
698  memset (&a6, 0, sizeof(a6));
699 #if HAVE_SOCKADDR_IN_SIN_LEN
700  a6.sin6_len = sizeof (a6);
701 #endif
702  a6.sin6_family = AF_INET6;
703  a6.sin6_port = u6->u6_port;
704  GNUNET_memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof(struct in6_addr));
705  sb = &a6;
706  sbs = sizeof(a6);
707  }
708  else if (addrlen == sizeof(struct IPv4UdpAddress))
709  {
710  GNUNET_assert (NULL != address->address); /* make static analysis happy */
711  u4 = address->address;
712  memset (&a4, 0, sizeof(a4));
713 #if HAVE_SOCKADDR_IN_SIN_LEN
714  a4.sin_len = sizeof (a4);
715 #endif
716  a4.sin_family = AF_INET;
717  a4.sin_port = u4->u4_port;
718  a4.sin_addr.s_addr = u4->ipv4_addr;
719  sb = &a4;
720  sbs = sizeof(a4);
721  }
722  else
723  {
724  GNUNET_break (0);
725  return GNUNET_NT_UNSPECIFIED;
726  }
727  return plugin->env->get_address_type (plugin->env->cls,
728  sb,
729  sbs);
730 }
731 
732 
733 /* ******************* Event loop ******************** */
734 
742 static void
743 udp_plugin_select_v4 (void *cls);
744 
745 
753 static void
754 udp_plugin_select_v6 (void *cls);
755 
756 
762 static void
764 {
765  struct GNUNET_TIME_Relative min_delay;
766  struct GNUNET_TIME_Relative delay;
767  struct UDP_MessageWrapper *udpw;
768  struct UDP_MessageWrapper *min_udpw;
769 
770  if ( (GNUNET_YES == plugin->enable_ipv4) &&
771  (NULL != plugin->sockv4) )
772  {
773  /* Find a message ready to send:
774  * Flow delay from other peer is expired or not set (0) */
775  min_delay = GNUNET_TIME_UNIT_FOREVER_REL;
776  min_udpw = NULL;
777  for (udpw = plugin->ipv4_queue_head; NULL != udpw; udpw = udpw->next)
778  {
780  if (delay.rel_value_us < min_delay.rel_value_us)
781  {
782  min_delay = delay;
783  min_udpw = udpw;
784  }
785  }
786  if (NULL != plugin->select_task_v4)
788  if (NULL != min_udpw)
789  {
790  if (min_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
791  {
793  "Calculated flow delay for UDPv4 at %s for %s\n",
795  GNUNET_YES),
796  GNUNET_i2s (&min_udpw->session->target));
797  }
798  else
799  {
801  "Calculated flow delay for UDPv4 at %s for %s\n",
803  GNUNET_YES),
804  GNUNET_i2s (&min_udpw->session->target));
805  }
806  }
807  plugin->select_task_v4
808  = GNUNET_SCHEDULER_add_read_net (min_delay,
809  plugin->sockv4,
810  &udp_plugin_select_v4,
811  plugin);
812  }
813 }
814 
815 
821 static void
823 {
824  struct GNUNET_TIME_Relative min_delay;
825  struct GNUNET_TIME_Relative delay;
826  struct UDP_MessageWrapper *udpw;
827  struct UDP_MessageWrapper *min_udpw;
828 
829  if ( (GNUNET_YES == plugin->enable_ipv6) &&
830  (NULL != plugin->sockv6) )
831  {
832  min_delay = GNUNET_TIME_UNIT_FOREVER_REL;
833  min_udpw = NULL;
834  for (udpw = plugin->ipv6_queue_head; NULL != udpw; udpw = udpw->next)
835  {
837  if (delay.rel_value_us < min_delay.rel_value_us)
838  {
839  min_delay = delay;
840  min_udpw = udpw;
841  }
842  }
843  if (NULL != plugin->select_task_v6)
845  if (NULL != min_udpw)
846  {
847  if (min_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
848  {
850  "Calculated flow delay for UDPv6 at %s for %s\n",
852  GNUNET_YES),
853  GNUNET_i2s (&min_udpw->session->target));
854  }
855  else
856  {
858  "Calculated flow delay for UDPv6 at %s for %s\n",
860  GNUNET_YES),
861  GNUNET_i2s (&min_udpw->session->target));
862  }
863  }
864  plugin->select_task_v6
865  = GNUNET_SCHEDULER_add_read_net (min_delay,
866  plugin->sockv6,
867  &udp_plugin_select_v6,
868  plugin);
869  }
870 }
871 
872 
873 /* ******************* Address to string and back ***************** */
874 
875 
887 const char *
889  const void *addr,
890  size_t addrlen)
891 {
892  static char rbuf[INET6_ADDRSTRLEN + 10];
893  char buf[INET6_ADDRSTRLEN];
894  const void *sb;
895  struct in_addr a4;
896  struct in6_addr a6;
897  const struct IPv4UdpAddress *t4;
898  const struct IPv6UdpAddress *t6;
899  int af;
900  uint16_t port;
901  uint32_t options;
902 
903  if (NULL == addr)
904  {
905  GNUNET_break_op (0);
906  return NULL;
907  }
908 
909  if (addrlen == sizeof(struct IPv6UdpAddress))
910  {
911  t6 = addr;
912  af = AF_INET6;
913  options = ntohl (t6->options);
914  port = ntohs (t6->u6_port);
915  a6 = t6->ipv6_addr;
916  sb = &a6;
917  }
918  else if (addrlen == sizeof(struct IPv4UdpAddress))
919  {
920  t4 = addr;
921  af = AF_INET;
922  options = ntohl (t4->options);
923  port = ntohs (t4->u4_port);
924  a4.s_addr = t4->ipv4_addr;
925  sb = &a4;
926  }
927  else
928  {
929  GNUNET_break_op (0);
930  return NULL;
931  }
932  inet_ntop (af,
933  sb,
934  buf,
935  INET6_ADDRSTRLEN);
936  GNUNET_snprintf (rbuf,
937  sizeof(rbuf),
938  (af == AF_INET6)
939  ? "%s.%u.[%s]:%u"
940  : "%s.%u.%s:%u",
941  PLUGIN_NAME,
942  options,
943  buf,
944  port);
945  return rbuf;
946 }
947 
948 
960 static int
962  const char *addr,
963  uint16_t addrlen,
964  void **buf,
965  size_t *added)
966 {
967  struct sockaddr_storage socket_address;
968  char *address;
969  char *plugin;
970  char *optionstr;
971  uint32_t options;
972 
973  /* Format tcp.options.address:port */
974  address = NULL;
975  plugin = NULL;
976  optionstr = NULL;
977 
978  if ((NULL == addr) || (0 == addrlen))
979  {
980  GNUNET_break (0);
981  return GNUNET_SYSERR;
982  }
983  if ('\0' != addr[addrlen - 1])
984  {
985  GNUNET_break (0);
986  return GNUNET_SYSERR;
987  }
988  if (strlen (addr) != addrlen - 1)
989  {
990  GNUNET_break (0);
991  return GNUNET_SYSERR;
992  }
993  plugin = GNUNET_strdup (addr);
994  optionstr = strchr (plugin, '.');
995  if (NULL == optionstr)
996  {
997  GNUNET_break (0);
998  GNUNET_free (plugin);
999  return GNUNET_SYSERR;
1000  }
1001  optionstr[0] = '\0';
1002  optionstr++;
1003  options = atol (optionstr);
1004  address = strchr (optionstr, '.');
1005  if (NULL == address)
1006  {
1007  GNUNET_break (0);
1008  GNUNET_free (plugin);
1009  return GNUNET_SYSERR;
1010  }
1011  address[0] = '\0';
1012  address++;
1013 
1014  if (GNUNET_OK !=
1016  strlen (address),
1017  &socket_address))
1018  {
1019  GNUNET_break (0);
1020  GNUNET_free (plugin);
1021  return GNUNET_SYSERR;
1022  }
1023  GNUNET_free(plugin);
1024 
1025  switch (socket_address.ss_family)
1026  {
1027  case AF_INET:
1028  {
1029  struct IPv4UdpAddress *u4;
1030  const struct sockaddr_in *in4 = (const struct sockaddr_in *) &socket_address;
1031 
1032  u4 = GNUNET_new (struct IPv4UdpAddress);
1033  u4->options = htonl (options);
1034  u4->ipv4_addr = in4->sin_addr.s_addr;
1035  u4->u4_port = in4->sin_port;
1036  *buf = u4;
1037  *added = sizeof (struct IPv4UdpAddress);
1038  return GNUNET_OK;
1039  }
1040  case AF_INET6:
1041  {
1042  struct IPv6UdpAddress *u6;
1043  const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *) &socket_address;
1044 
1045  u6 = GNUNET_new (struct IPv6UdpAddress);
1046  u6->options = htonl (options);
1047  u6->ipv6_addr = in6->sin6_addr;
1048  u6->u6_port = in6->sin6_port;
1049  *buf = u6;
1050  *added = sizeof (struct IPv6UdpAddress);
1051  return GNUNET_OK;
1052  }
1053  default:
1054  GNUNET_break (0);
1055  return GNUNET_SYSERR;
1056  }
1057 }
1058 
1059 
1066 static void
1067 append_port (void *cls,
1068  const char *hostname)
1069 {
1070  struct PrettyPrinterContext *ppc = cls;
1071  struct Plugin *plugin = ppc->plugin;
1072  char *ret;
1073 
1074  if (NULL == hostname)
1075  {
1076  /* Final call, done */
1078  plugin->ppc_dll_tail,
1079  ppc);
1080  ppc->resolver_handle = NULL;
1081  ppc->asc (ppc->asc_cls,
1082  NULL,
1083  GNUNET_OK);
1084  GNUNET_free (ppc);
1085  return;
1086  }
1087  if (GNUNET_YES == ppc->ipv6)
1088  GNUNET_asprintf (&ret,
1089  "%s.%u.[%s]:%d",
1090  PLUGIN_NAME,
1091  ppc->options,
1092  hostname,
1093  ppc->port);
1094  else
1095  GNUNET_asprintf (&ret,
1096  "%s.%u.%s:%d",
1097  PLUGIN_NAME,
1098  ppc->options,
1099  hostname,
1100  ppc->port);
1101  ppc->asc (ppc->asc_cls,
1102  ret,
1103  GNUNET_OK);
1104  GNUNET_free (ret);
1105 }
1106 
1107 
1122 static void
1124  const char *type,
1125  const void *addr,
1126  size_t addrlen,
1127  int numeric,
1130  void *asc_cls)
1131 {
1132  struct Plugin *plugin = cls;
1133  struct PrettyPrinterContext *ppc;
1134  const struct sockaddr *sb;
1135  size_t sbs;
1136  struct sockaddr_in a4;
1137  struct sockaddr_in6 a6;
1138  const struct IPv4UdpAddress *u4;
1139  const struct IPv6UdpAddress *u6;
1140  uint16_t port;
1141  uint32_t options;
1142 
1143  if (addrlen == sizeof(struct IPv6UdpAddress))
1144  {
1145  u6 = addr;
1146  memset (&a6,
1147  0,
1148  sizeof (a6));
1149  a6.sin6_family = AF_INET6;
1150 #if HAVE_SOCKADDR_IN_SIN_LEN
1151  a6.sin6_len = sizeof (a6);
1152 #endif
1153  a6.sin6_port = u6->u6_port;
1154  a6.sin6_addr = u6->ipv6_addr;
1155  port = ntohs (u6->u6_port);
1156  options = ntohl (u6->options);
1157  sb = (const struct sockaddr *) &a6;
1158  sbs = sizeof (a6);
1159  }
1160  else if (addrlen == sizeof (struct IPv4UdpAddress))
1161  {
1162  u4 = addr;
1163  memset (&a4,
1164  0,
1165  sizeof(a4));
1166  a4.sin_family = AF_INET;
1167 #if HAVE_SOCKADDR_IN_SIN_LEN
1168  a4.sin_len = sizeof (a4);
1169 #endif
1170  a4.sin_port = u4->u4_port;
1171  a4.sin_addr.s_addr = u4->ipv4_addr;
1172  port = ntohs (u4->u4_port);
1173  options = ntohl (u4->options);
1174  sb = (const struct sockaddr *) &a4;
1175  sbs = sizeof(a4);
1176  }
1177  else
1178  {
1179  /* invalid address */
1180  GNUNET_break_op (0);
1181  asc (asc_cls,
1182  NULL,
1183  GNUNET_SYSERR);
1184  asc (asc_cls,
1185  NULL,
1186  GNUNET_OK);
1187  return;
1188  }
1189  ppc = GNUNET_new (struct PrettyPrinterContext);
1190  ppc->plugin = plugin;
1191  ppc->asc = asc;
1192  ppc->asc_cls = asc_cls;
1193  ppc->port = port;
1194  ppc->options = options;
1195  if (addrlen == sizeof (struct IPv6UdpAddress))
1196  ppc->ipv6 = GNUNET_YES;
1197  else
1198  ppc->ipv6 = GNUNET_NO;
1200  plugin->ppc_dll_tail,
1201  ppc);
1202  ppc->resolver_handle
1204  sbs,
1205  ! numeric,
1206  timeout,
1207  &append_port,
1208  ppc);
1209 }
1210 
1211 
1221 static int
1222 check_port (const struct Plugin *plugin,
1223  uint16_t in_port)
1224 {
1225  if ( (plugin->port == in_port) ||
1226  (plugin->aport == in_port) )
1227  return GNUNET_OK;
1228  return GNUNET_SYSERR;
1229 }
1230 
1231 
1247 static int
1249  const void *addr,
1250  size_t addrlen)
1251 {
1252  struct Plugin *plugin = cls;
1253  const struct IPv4UdpAddress *v4;
1254  const struct IPv6UdpAddress *v6;
1255 
1256  if (sizeof(struct IPv4UdpAddress) == addrlen)
1257  {
1258  struct sockaddr_in s4;
1259 
1260  v4 = (const struct IPv4UdpAddress *) addr;
1261  if (GNUNET_OK != check_port (plugin,
1262  ntohs (v4->u4_port)))
1263  return GNUNET_SYSERR;
1264  memset (&s4, 0, sizeof (s4));
1265  s4.sin_family = AF_INET;
1266 #if HAVE_SOCKADDR_IN_SIN_LEN
1267  s4.sin_len = sizeof (s4);
1268 #endif
1269  s4.sin_port = v4->u4_port;
1270  s4.sin_addr.s_addr = v4->ipv4_addr;
1271 
1272  if (GNUNET_OK !=
1273  GNUNET_NAT_test_address (plugin->nat,
1274  &s4,
1275  sizeof (struct sockaddr_in)))
1276  return GNUNET_SYSERR;
1277  }
1278  else if (sizeof(struct IPv6UdpAddress) == addrlen)
1279  {
1280  struct sockaddr_in6 s6;
1281 
1282  v6 = (const struct IPv6UdpAddress *) addr;
1283  if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
1284  return GNUNET_OK; /* plausible, if unlikely... */
1285  memset (&s6, 0, sizeof (s6));
1286  s6.sin6_family = AF_INET6;
1287 #if HAVE_SOCKADDR_IN_SIN_LEN
1288  s6.sin6_len = sizeof (s6);
1289 #endif
1290  s6.sin6_port = v6->u6_port;
1291  s6.sin6_addr = v6->ipv6_addr;
1292 
1293  if (GNUNET_OK !=
1294  GNUNET_NAT_test_address (plugin->nat,
1295  &s6,
1296  sizeof(struct sockaddr_in6)))
1297  return GNUNET_SYSERR;
1298  }
1299  else
1300  {
1301  GNUNET_break_op (0);
1302  return GNUNET_SYSERR;
1303  }
1304  return GNUNET_OK;
1305 }
1306 
1307 
1320 static void
1322  void **app_ctx,
1323  int add_remove,
1325  const struct sockaddr *addr,
1326  socklen_t addrlen)
1327 {
1328  struct Plugin *plugin = cls;
1329  struct GNUNET_HELLO_Address *address;
1330  struct IPv4UdpAddress u4;
1331  struct IPv6UdpAddress u6;
1332  void *arg;
1333  size_t args;
1334 
1335  (void) app_ctx;
1337  (GNUNET_YES == add_remove)
1338  ? "NAT notification to add address `%s'\n"
1339  : "NAT notification to remove address `%s'\n",
1340  GNUNET_a2s (addr,
1341  addrlen));
1342  /* convert 'address' to our internal format */
1343  switch (addr->sa_family)
1344  {
1345  case AF_INET:
1346  {
1347  const struct sockaddr_in *i4;
1348 
1349  GNUNET_assert (sizeof(struct sockaddr_in) == addrlen);
1350  i4 = (const struct sockaddr_in *) addr;
1351  if (0 == ntohs (i4->sin_port))
1352  return; /* Port = 0 means unmapped, ignore these for UDP. */
1353  memset (&u4,
1354  0,
1355  sizeof(u4));
1356  u4.options = htonl (plugin->myoptions);
1357  u4.ipv4_addr = i4->sin_addr.s_addr;
1358  u4.u4_port = i4->sin_port;
1359  arg = &u4;
1360  args = sizeof (struct IPv4UdpAddress);
1361  break;
1362  }
1363  case AF_INET6:
1364  {
1365  const struct sockaddr_in6 *i6;
1366 
1367  GNUNET_assert (sizeof(struct sockaddr_in6) == addrlen);
1368  i6 = (const struct sockaddr_in6 *) addr;
1369  if (0 == ntohs (i6->sin6_port))
1370  return; /* Port = 0 means unmapped, ignore these for UDP. */
1371  memset (&u6,
1372  0,
1373  sizeof(u6));
1374  u6.options = htonl (plugin->myoptions);
1375  u6.ipv6_addr = i6->sin6_addr;
1376  u6.u6_port = i6->sin6_port;
1377  arg = &u6;
1378  args = sizeof (struct IPv6UdpAddress);
1379  break;
1380  }
1381  default:
1382  GNUNET_break (0);
1383  return;
1384  }
1385  /* modify our published address list */
1386  /* TODO: use 'ac' here in the future... */
1387  address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1388  PLUGIN_NAME,
1389  arg,
1390  args,
1392  plugin->env->notify_address (plugin->env->cls,
1393  add_remove,
1394  address);
1395  GNUNET_HELLO_address_free (address);
1396 }
1397 
1398 
1399 /* ********************* Finding sessions ******************* */
1400 
1401 
1406 {
1411 
1416 };
1417 
1418 
1427 static int
1428 session_cmp_it (void *cls,
1429  const struct GNUNET_PeerIdentity *key,
1430  void *value)
1431 {
1432  struct GNUNET_ATS_SessionCompareContext *cctx = cls;
1433  struct GNUNET_ATS_Session *s = value;
1434 
1435  if (0 == GNUNET_HELLO_address_cmp (s->address,
1436  cctx->address))
1437  {
1439  cctx->res = s;
1440  return GNUNET_NO;
1441  }
1442  return GNUNET_OK;
1443 }
1444 
1445 
1455 static struct GNUNET_ATS_Session *
1457  const struct GNUNET_HELLO_Address *address)
1458 {
1459  struct Plugin *plugin = cls;
1460  const struct IPv6UdpAddress *udp_a6;
1461  const struct IPv4UdpAddress *udp_a4;
1463 
1464  if (NULL == address->address)
1465  {
1466  GNUNET_break (0);
1467  return NULL;
1468  }
1469  if (sizeof(struct IPv4UdpAddress) == address->address_length)
1470  {
1471  if (NULL == plugin->sockv4)
1472  return NULL;
1473  udp_a4 = (const struct IPv4UdpAddress *) address->address;
1474  if (0 == udp_a4->u4_port)
1475  {
1476  GNUNET_break (0);
1477  return NULL;
1478  }
1479  }
1480  else if (sizeof(struct IPv6UdpAddress) == address->address_length)
1481  {
1482  if (NULL == plugin->sockv6)
1483  return NULL;
1484  udp_a6 = (const struct IPv6UdpAddress *) address->address;
1485  if (0 == udp_a6->u6_port)
1486  {
1487  GNUNET_break (0);
1488  return NULL;
1489  }
1490  }
1491  else
1492  {
1493  GNUNET_break (0);
1494  return NULL;
1495  }
1496 
1497  /* check if session already exists */
1498  cctx.address = address;
1499  cctx.res = NULL;
1501  "Looking for existing session for peer `%s' with address `%s'\n",
1502  GNUNET_i2s (&address->peer),
1503  udp_address_to_string (plugin,
1504  address->address,
1505  address->address_length));
1507  &address->peer,
1508  &session_cmp_it,
1509  &cctx);
1510  if (NULL == cctx.res)
1511  return NULL;
1513  "Found existing session %p\n",
1514  cctx.res);
1515  return cctx.res;
1516 }
1517 
1518 
1519 /* ********************** Timeout ****************** */
1520 
1521 
1527 static void
1529 {
1530  if (GNUNET_YES == s->in_destroy)
1531  return;
1532  GNUNET_assert (NULL != s->timeout_task);
1534 }
1535 
1536 
1537 
1547 static void
1549  const struct GNUNET_PeerIdentity *peer,
1550  struct GNUNET_ATS_Session *session)
1551 {
1552  struct Plugin *plugin = cls;
1553 
1554  if (GNUNET_YES !=
1556  peer,
1557  session))
1558  {
1559  GNUNET_break (0);
1560  return;
1561  }
1562  /* Reschedule session timeout */
1563  reschedule_session_timeout (session);
1564 }
1565 
1566 
1567 /* ************************* Sending ************************ */
1568 
1569 
1577 static void
1579  struct UDP_MessageWrapper *udpw)
1580 {
1581  struct GNUNET_ATS_Session *session = udpw->session;
1582 
1583  if (plugin->bytes_in_buffer < udpw->msg_size)
1584  {
1585  GNUNET_break (0);
1586  }
1587  else
1588  {
1589  GNUNET_STATISTICS_update (plugin->env->stats,
1590  "# UDP, total bytes in send buffers",
1591  - (long long) udpw->msg_size,
1592  GNUNET_NO);
1593  plugin->bytes_in_buffer -= udpw->msg_size;
1594  }
1595  GNUNET_STATISTICS_update (plugin->env->stats,
1596  "# UDP, total messages in send buffers",
1597  -1,
1598  GNUNET_NO);
1599  if (sizeof(struct IPv4UdpAddress) == udpw->session->address->address_length)
1600  {
1602  plugin->ipv4_queue_tail,
1603  udpw);
1604  }
1605  else if (sizeof(struct IPv6UdpAddress) == udpw->session->address->address_length)
1606  {
1608  plugin->ipv6_queue_tail,
1609  udpw);
1610  }
1611  else
1612  {
1613  GNUNET_break (0);
1614  return;
1615  }
1616  GNUNET_assert (session->msgs_in_queue > 0);
1617  session->msgs_in_queue--;
1618  GNUNET_assert (session->bytes_in_queue >= udpw->msg_size);
1619  session->bytes_in_queue -= udpw->msg_size;
1620 }
1621 
1622 
1629 static void
1631  struct UDP_MessageWrapper *udpw)
1632 {
1633  struct GNUNET_ATS_Session *session = udpw->session;
1634 
1635  if (GNUNET_YES == session->in_destroy)
1636  {
1637  GNUNET_break (0);
1638  GNUNET_free (udpw);
1639  return;
1640  }
1641  if (plugin->bytes_in_buffer > INT64_MAX - udpw->msg_size)
1642  {
1643  GNUNET_break (0);
1644  }
1645  else
1646  {
1647  GNUNET_STATISTICS_update (plugin->env->stats,
1648  "# UDP, total bytes in send buffers",
1649  udpw->msg_size,
1650  GNUNET_NO);
1651  plugin->bytes_in_buffer += udpw->msg_size;
1652  }
1653  GNUNET_STATISTICS_update (plugin->env->stats,
1654  "# UDP, total messages in send buffers",
1655  1,
1656  GNUNET_NO);
1657  if (sizeof (struct IPv4UdpAddress) == udpw->session->address->address_length)
1658  {
1660  plugin->ipv4_queue_tail,
1661  udpw);
1662  }
1663  else if (sizeof (struct IPv6UdpAddress) == udpw->session->address->address_length)
1664  {
1666  plugin->ipv6_queue_tail,
1667  udpw);
1668  }
1669  else
1670  {
1671  GNUNET_break (0);
1672  udpw->cont (udpw->cont_cls,
1673  &session->target,
1674  GNUNET_SYSERR,
1675  udpw->msg_size,
1676  0);
1677  GNUNET_free (udpw);
1678  return;
1679  }
1680  session->msgs_in_queue++;
1681  session->bytes_in_queue += udpw->msg_size;
1682 }
1683 
1684 
1695 static void
1697  int result)
1698 {
1699  struct Plugin *plugin = frag_ctx->plugin;
1700  struct GNUNET_ATS_Session *s = frag_ctx->session;
1701  struct UDP_MessageWrapper *udpw;
1702  struct UDP_MessageWrapper *tmp;
1703  size_t overhead;
1704  struct GNUNET_TIME_Relative delay;
1705 
1707  "%p: Fragmented message removed with result %s\n",
1708  frag_ctx,
1709  (result == GNUNET_SYSERR) ? "FAIL" : "SUCCESS");
1710  /* Call continuation for fragmented message */
1711  if (frag_ctx->on_wire_size >= frag_ctx->payload_size)
1712  overhead = frag_ctx->on_wire_size - frag_ctx->payload_size;
1713  else
1714  overhead = frag_ctx->on_wire_size;
1715  delay = GNUNET_TIME_absolute_get_duration (frag_ctx->start_time);
1716  if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
1717  {
1719  "Fragmented message acknowledged after %s (expected at %s)\n",
1721  GNUNET_YES),
1723  }
1724  else
1725  {
1727  "Fragmented message acknowledged after %s (expected at %s)\n",
1729  GNUNET_YES),
1731  }
1732 
1733  if (NULL != frag_ctx->cont)
1734  frag_ctx->cont (frag_ctx->cont_cls,
1735  &s->target,
1736  result,
1737  s->frag_ctx->payload_size,
1738  frag_ctx->on_wire_size);
1739  GNUNET_STATISTICS_update (plugin->env->stats,
1740  "# UDP, fragmented messages active",
1741  -1,
1742  GNUNET_NO);
1743 
1744  if (GNUNET_OK == result)
1745  {
1746  GNUNET_STATISTICS_update (plugin->env->stats,
1747  "# UDP, fragmented msgs, messages, sent, success",
1748  1,
1749  GNUNET_NO);
1750  GNUNET_STATISTICS_update (plugin->env->stats,
1751  "# UDP, fragmented msgs, bytes payload, sent, success",
1752  s->frag_ctx->payload_size,
1753  GNUNET_NO);
1754  GNUNET_STATISTICS_update (plugin->env->stats,
1755  "# UDP, fragmented msgs, bytes overhead, sent, success",
1756  overhead,
1757  GNUNET_NO);
1758  GNUNET_STATISTICS_update (plugin->env->stats,
1759  "# UDP, total, bytes overhead, sent",
1760  overhead,
1761  GNUNET_NO);
1762  GNUNET_STATISTICS_update (plugin->env->stats,
1763  "# UDP, total, bytes payload, sent",
1764  s->frag_ctx->payload_size,
1765  GNUNET_NO);
1766  }
1767  else
1768  {
1769  GNUNET_STATISTICS_update (plugin->env->stats,
1770  "# UDP, fragmented msgs, messages, sent, failure",
1771  1,
1772  GNUNET_NO);
1773  GNUNET_STATISTICS_update (plugin->env->stats,
1774  "# UDP, fragmented msgs, bytes payload, sent, failure",
1775  s->frag_ctx->payload_size,
1776  GNUNET_NO);
1777  GNUNET_STATISTICS_update (plugin->env->stats,
1778  "# UDP, fragmented msgs, bytes payload, sent, failure",
1779  overhead,
1780  GNUNET_NO);
1781  GNUNET_STATISTICS_update (plugin->env->stats,
1782  "# UDP, fragmented msgs, bytes payload, sent, failure",
1783  overhead,
1784  GNUNET_NO);
1785  }
1786 
1787  /* Remove remaining fragments from queue, no need to transmit those
1788  any longer. */
1789  if (s->address->address_length == sizeof(struct IPv6UdpAddress))
1790  {
1791  udpw = plugin->ipv6_queue_head;
1792  while (NULL != udpw)
1793  {
1794  tmp = udpw->next;
1795  if ( (udpw->frag_ctx != NULL) &&
1796  (udpw->frag_ctx == frag_ctx) )
1797  {
1798  dequeue (plugin,
1799  udpw);
1800  GNUNET_free (udpw);
1801  }
1802  udpw = tmp;
1803  }
1804  }
1805  if (s->address->address_length == sizeof(struct IPv4UdpAddress))
1806  {
1807  udpw = plugin->ipv4_queue_head;
1808  while (NULL != udpw)
1809  {
1810  tmp = udpw->next;
1811  if ( (NULL != udpw->frag_ctx) &&
1812  (udpw->frag_ctx == frag_ctx) )
1813  {
1814  dequeue (plugin,
1815  udpw);
1816  GNUNET_free (udpw);
1817  }
1818  udpw = tmp;
1819  }
1820  }
1822  s,
1827  s->frag_ctx = NULL;
1828  GNUNET_free (frag_ctx);
1829 }
1830 
1831 
1840 static void
1841 qc_fragment_sent (void *cls,
1842  struct UDP_MessageWrapper *udpw,
1843  int result)
1844 {
1845  struct Plugin *plugin = cls;
1846 
1847  GNUNET_assert (NULL != udpw->frag_ctx);
1848  if (GNUNET_OK == result)
1849  {
1851  "Fragment of message with %u bytes transmitted to %s\n",
1852  (unsigned int) udpw->payload_size,
1853  GNUNET_i2s (&udpw->session->target));
1855  GNUNET_STATISTICS_update (plugin->env->stats,
1856  "# UDP, fragmented msgs, fragments, sent, success",
1857  1,
1858  GNUNET_NO);
1859  GNUNET_STATISTICS_update (plugin->env->stats,
1860  "# UDP, fragmented msgs, fragments bytes, sent, success",
1861  udpw->msg_size,
1862  GNUNET_NO);
1863  }
1864  else
1865  {
1867  "Failed to transmit fragment of message with %u bytes to %s\n",
1868  (unsigned int) udpw->payload_size,
1869  GNUNET_i2s (&udpw->session->target));
1871  GNUNET_SYSERR);
1872  GNUNET_STATISTICS_update (plugin->env->stats,
1873  "# UDP, fragmented msgs, fragments, sent, failure",
1874  1,
1875  GNUNET_NO);
1876  GNUNET_STATISTICS_update (plugin->env->stats,
1877  "# UDP, fragmented msgs, fragments bytes, sent, failure",
1878  udpw->msg_size,
1879  GNUNET_NO);
1880  }
1881 }
1882 
1883 
1893 static void
1894 enqueue_fragment (void *cls,
1895  const struct GNUNET_MessageHeader *msg)
1896 {
1897  struct UDP_FragmentationContext *frag_ctx = cls;
1898  struct Plugin *plugin = frag_ctx->plugin;
1899  struct UDP_MessageWrapper *udpw;
1900  struct GNUNET_ATS_Session *session = frag_ctx->session;
1901  size_t msg_len = ntohs (msg->size);
1902 
1904  "Enqueuing fragment with %u bytes\n",
1905  msg_len);
1906  udpw = GNUNET_malloc (sizeof (struct UDP_MessageWrapper) + msg_len);
1907  udpw->session = session;
1908  udpw->msg_buf = (char *) &udpw[1];
1909  udpw->msg_size = msg_len;
1910  udpw->payload_size = msg_len; /* FIXME: minus fragment overhead */
1911  udpw->timeout = frag_ctx->timeout;
1912  udpw->start_time = frag_ctx->start_time;
1913  udpw->transmission_time = frag_ctx->next_frag_time;
1914  frag_ctx->next_frag_time
1916  frag_ctx->flow_delay_from_other_peer);
1917  udpw->frag_ctx = frag_ctx;
1918  udpw->qc = &qc_fragment_sent;
1919  udpw->qc_cls = plugin;
1920  GNUNET_memcpy (udpw->msg_buf,
1921  msg,
1922  msg_len);
1923  enqueue (plugin,
1924  udpw);
1925  if (session->address->address_length == sizeof (struct IPv4UdpAddress))
1926  schedule_select_v4 (plugin);
1927  else
1928  schedule_select_v6 (plugin);
1929 }
1930 
1931 
1940 static void
1941 qc_message_sent (void *cls,
1942  struct UDP_MessageWrapper *udpw,
1943  int result)
1944 {
1945  struct Plugin *plugin = cls;
1946  size_t overhead;
1947  struct GNUNET_TIME_Relative delay;
1948 
1949  if (udpw->msg_size >= udpw->payload_size)
1950  overhead = udpw->msg_size - udpw->payload_size;
1951  else
1952  overhead = udpw->msg_size;
1953 
1954  if (NULL != udpw->cont)
1955  {
1957  if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
1958  {
1960  "Message sent via UDP with delay of %s\n",
1962  GNUNET_YES));
1963  }
1964  else
1965  {
1967  "Message sent via UDP with delay of %s\n",
1969  GNUNET_YES));
1970  }
1971  udpw->cont (udpw->cont_cls,
1972  &udpw->session->target,
1973  result,
1974  udpw->payload_size,
1975  overhead);
1976  }
1977  if (GNUNET_OK == result)
1978  {
1979  GNUNET_STATISTICS_update (plugin->env->stats,
1980  "# UDP, unfragmented msgs, messages, sent, success",
1981  1,
1982  GNUNET_NO);
1983  GNUNET_STATISTICS_update (plugin->env->stats,
1984  "# UDP, unfragmented msgs, bytes payload, sent, success",
1985  udpw->payload_size,
1986  GNUNET_NO);
1987  GNUNET_STATISTICS_update (plugin->env->stats,
1988  "# UDP, unfragmented msgs, bytes overhead, sent, success",
1989  overhead,
1990  GNUNET_NO);
1991  GNUNET_STATISTICS_update (plugin->env->stats,
1992  "# UDP, total, bytes overhead, sent",
1993  overhead,
1994  GNUNET_NO);
1995  GNUNET_STATISTICS_update (plugin->env->stats,
1996  "# UDP, total, bytes payload, sent",
1997  udpw->payload_size,
1998  GNUNET_NO);
1999  }
2000  else
2001  {
2002  GNUNET_STATISTICS_update (plugin->env->stats,
2003  "# UDP, unfragmented msgs, messages, sent, failure",
2004  1,
2005  GNUNET_NO);
2006  GNUNET_STATISTICS_update (plugin->env->stats,
2007  "# UDP, unfragmented msgs, bytes payload, sent, failure",
2008  udpw->payload_size,
2009  GNUNET_NO);
2010  GNUNET_STATISTICS_update (plugin->env->stats,
2011  "# UDP, unfragmented msgs, bytes overhead, sent, failure",
2012  overhead,
2013  GNUNET_NO);
2014  }
2015 }
2016 
2017 
2045 static ssize_t
2046 udp_plugin_send (void *cls,
2047  struct GNUNET_ATS_Session *s,
2048  const char *msgbuf,
2049  size_t msgbuf_size,
2050  unsigned int priority,
2051  struct GNUNET_TIME_Relative to,
2053  void *cont_cls)
2054 {
2055  struct Plugin *plugin = cls;
2056  size_t udpmlen = msgbuf_size + sizeof(struct UDPMessage);
2057  struct UDP_FragmentationContext *frag_ctx;
2058  struct UDP_MessageWrapper *udpw;
2059  struct UDPMessage *udp;
2060  char mbuf[udpmlen] GNUNET_ALIGN;
2061  struct GNUNET_TIME_Relative latency;
2062 
2063  if ( (sizeof(struct IPv6UdpAddress) == s->address->address_length) &&
2064  (NULL == plugin->sockv6) )
2065  return GNUNET_SYSERR;
2066  if ( (sizeof(struct IPv4UdpAddress) == s->address->address_length) &&
2067  (NULL == plugin->sockv4) )
2068  return GNUNET_SYSERR;
2069  if (udpmlen >= GNUNET_MAX_MESSAGE_SIZE)
2070  {
2071  GNUNET_break (0);
2072  return GNUNET_SYSERR;
2073  }
2074  if (GNUNET_YES !=
2076  &s->target,
2077  s))
2078  {
2079  GNUNET_break (0);
2080  return GNUNET_SYSERR;
2081  }
2083  "UDP transmits %u-byte message to `%s' using address `%s'\n",
2084  udpmlen,
2085  GNUNET_i2s (&s->target),
2086  udp_address_to_string (plugin,
2087  s->address->address,
2088  s->address->address_length));
2089 
2090  udp = (struct UDPMessage *) mbuf;
2091  udp->header.size = htons (udpmlen);
2093  udp->reserved = htonl (0);
2094  udp->sender = *plugin->env->my_identity;
2095 
2096  /* We do not update the session time out here! Otherwise this
2097  * session will not timeout since we send keep alive before session
2098  * can timeout.
2099  *
2100  * For UDP we update session timeout only on receive, this will
2101  * cover keep alives, since remote peer will reply with keep alive
2102  * responses!
2103  */
2104  if (udpmlen <= UDP_MTU)
2105  {
2106  /* unfragmented message */
2107  udpw = GNUNET_malloc (sizeof (struct UDP_MessageWrapper) + udpmlen);
2108  udpw->session = s;
2109  udpw->msg_buf = (char *) &udpw[1];
2110  udpw->msg_size = udpmlen; /* message size with UDP overhead */
2111  udpw->payload_size = msgbuf_size; /* message size without UDP overhead */
2118  udpw->cont = cont;
2119  udpw->cont_cls = cont_cls;
2120  udpw->frag_ctx = NULL;
2121  udpw->qc = &qc_message_sent;
2122  udpw->qc_cls = plugin;
2123  GNUNET_memcpy (udpw->msg_buf,
2124  udp,
2125  sizeof (struct UDPMessage));
2126  GNUNET_memcpy (&udpw->msg_buf[sizeof(struct UDPMessage)],
2127  msgbuf,
2128  msgbuf_size);
2129  enqueue (plugin,
2130  udpw);
2131  GNUNET_STATISTICS_update (plugin->env->stats,
2132  "# UDP, unfragmented messages queued total",
2133  1,
2134  GNUNET_NO);
2135  GNUNET_STATISTICS_update (plugin->env->stats,
2136  "# UDP, unfragmented bytes payload queued total",
2137  msgbuf_size,
2138  GNUNET_NO);
2139  if (s->address->address_length == sizeof (struct IPv4UdpAddress))
2140  schedule_select_v4 (plugin);
2141  else
2142  schedule_select_v6 (plugin);
2143  }
2144  else
2145  {
2146  /* fragmented message */
2147  if (NULL != s->frag_ctx)
2148  return GNUNET_SYSERR;
2149  GNUNET_memcpy (&udp[1],
2150  msgbuf,
2151  msgbuf_size);
2152  frag_ctx = GNUNET_new (struct UDP_FragmentationContext);
2153  frag_ctx->plugin = plugin;
2154  frag_ctx->session = s;
2155  frag_ctx->cont = cont;
2156  frag_ctx->cont_cls = cont_cls;
2157  frag_ctx->start_time = GNUNET_TIME_absolute_get ();
2158  frag_ctx->next_frag_time = s->last_transmit_time;
2159  frag_ctx->flow_delay_from_other_peer
2161  1 + (msgbuf_size /
2162  UDP_MTU));
2163  frag_ctx->timeout = GNUNET_TIME_relative_to_absolute (to);
2164  frag_ctx->payload_size = msgbuf_size; /* unfragmented message size without UDP overhead */
2165  frag_ctx->on_wire_size = 0; /* bytes with UDP and fragmentation overhead */
2166  frag_ctx->frag = GNUNET_FRAGMENT_context_create (plugin->env->stats,
2167  UDP_MTU,
2168  &plugin->tracker,
2171  &udp->header,
2173  frag_ctx);
2174  s->frag_ctx = frag_ctx;
2175  s->last_transmit_time = frag_ctx->next_frag_time;
2177  if (latency.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
2179  "Enqueued fragments will take %s for transmission to %s (queue size: %u)\n",
2181  GNUNET_YES),
2182  GNUNET_i2s (&s->target),
2183  (unsigned int) s->msgs_in_queue);
2184  else
2186  "Enqueued fragments will take %s for transmission to %s (queue size: %u)\n",
2188  GNUNET_YES),
2189  GNUNET_i2s (&s->target),
2190  (unsigned int) s->msgs_in_queue);
2191 
2192  GNUNET_STATISTICS_update (plugin->env->stats,
2193  "# UDP, fragmented messages active",
2194  1,
2195  GNUNET_NO);
2196  GNUNET_STATISTICS_update (plugin->env->stats,
2197  "# UDP, fragmented messages, total",
2198  1,
2199  GNUNET_NO);
2200  GNUNET_STATISTICS_update (plugin->env->stats,
2201  "# UDP, fragmented bytes (payload)",
2202  frag_ctx->payload_size,
2203  GNUNET_NO);
2204  }
2206  s,
2208  return udpmlen;
2209 }
2210 
2211 
2212 /* ********************** Receiving ********************** */
2213 
2214 
2219 {
2224 
2229 
2233  const union UdpAddress *udp_addr;
2234 
2239 
2240 };
2241 
2242 
2253 static int
2255  struct GNUNET_CONTAINER_HeapNode *node,
2256  void *element,
2258 {
2259  struct FindReceiveContext *frc = cls;
2260  struct DefragContext *e = element;
2261 
2262  if ( (frc->udp_addr_len == e->udp_addr_len) &&
2263  (0 == memcmp (frc->udp_addr,
2264  e->udp_addr,
2265  frc->udp_addr_len)) )
2266  {
2267  frc->rc = e;
2268  return GNUNET_NO;
2269  }
2270  return GNUNET_YES;
2271 }
2272 
2273 
2282 static int
2284  struct GNUNET_ATS_Session *s)
2285 {
2286  struct Plugin *plugin = cls;
2287  struct UDP_MessageWrapper *udpw;
2288  struct UDP_MessageWrapper *next;
2289  struct FindReceiveContext frc;
2290 
2293  "Session %p to peer `%s' at address %s ended\n",
2294  s,
2295  GNUNET_i2s (&s->target),
2296  udp_address_to_string (plugin,
2297  s->address->address,
2298  s->address->address_length));
2299  if (NULL != s->timeout_task)
2300  {
2302  s->timeout_task = NULL;
2303  }
2304  if (NULL != s->frag_ctx)
2305  {
2306  /* Remove fragmented message due to disconnect */
2308  GNUNET_SYSERR);
2309  }
2312  &s->target,
2313  s));
2314  frc.rc = NULL;
2315  frc.udp_addr = s->address->address;
2317  /* Lookup existing receive context for this address */
2318  if (NULL != plugin->defrag_ctxs)
2319  {
2322  &frc);
2323  if (NULL != frc.rc)
2324  {
2325  struct DefragContext *d_ctx = frc.rc;
2326 
2329  GNUNET_free (d_ctx);
2330  }
2331  }
2332  s->in_destroy = GNUNET_YES;
2333  next = plugin->ipv4_queue_head;
2334  while (NULL != (udpw = next))
2335  {
2336  next = udpw->next;
2337  if (udpw->session == s)
2338  {
2339  dequeue (plugin,
2340  udpw);
2341  udpw->qc (udpw->qc_cls,
2342  udpw,
2343  GNUNET_SYSERR);
2344  GNUNET_free (udpw);
2345  }
2346  }
2347  next = plugin->ipv6_queue_head;
2348  while (NULL != (udpw = next))
2349  {
2350  next = udpw->next;
2351  if (udpw->session == s)
2352  {
2353  dequeue (plugin,
2354  udpw);
2355  udpw->qc (udpw->qc_cls,
2356  udpw,
2357  GNUNET_SYSERR);
2358  GNUNET_free (udpw);
2359  }
2360  }
2361  if ( (NULL != s->frag_ctx) &&
2362  (NULL != s->frag_ctx->cont) )
2363  {
2364  /* The 'frag_ctx' itself will be freed in #free_session() a bit
2365  later, as it might be in use right now */
2367  "Calling continuation for fragemented message to `%s' with result SYSERR\n",
2368  GNUNET_i2s (&s->target));
2369  s->frag_ctx->cont (s->frag_ctx->cont_cls,
2370  &s->target,
2371  GNUNET_SYSERR,
2372  s->frag_ctx->payload_size,
2373  s->frag_ctx->on_wire_size);
2374  }
2376  s,
2378  plugin->env->session_end (plugin->env->cls,
2379  s->address,
2380  s);
2381  GNUNET_STATISTICS_set (plugin->env->stats,
2382  "# UDP sessions active",
2384  GNUNET_NO);
2385  if (0 == s->rc)
2386  free_session (s);
2387  return GNUNET_OK;
2388 }
2389 
2390 
2399 static void
2401  const struct GNUNET_MessageHeader *msg,
2402  const union UdpAddress *udp_addr,
2403  socklen_t udp_addr_len)
2404 {
2405  const struct GNUNET_MessageHeader *ack;
2406  const struct UDP_ACK_Message *udp_ack;
2407  struct GNUNET_HELLO_Address *address;
2408  struct GNUNET_ATS_Session *s;
2409  struct GNUNET_TIME_Relative flow_delay;
2410 
2411  /* check message format */
2412  if (ntohs (msg->size)
2413  < sizeof(struct UDP_ACK_Message) + sizeof(struct GNUNET_MessageHeader))
2414  {
2415  GNUNET_break_op (0);
2416  return;
2417  }
2418  udp_ack = (const struct UDP_ACK_Message *) msg;
2419  ack = (const struct GNUNET_MessageHeader *) &udp_ack[1];
2420  if (ntohs (ack->size) != ntohs (msg->size) - sizeof(struct UDP_ACK_Message))
2421  {
2422  GNUNET_break_op(0);
2423  return;
2424  }
2425 
2426  /* Locate session */
2427  address = GNUNET_HELLO_address_allocate (&udp_ack->sender,
2428  PLUGIN_NAME,
2429  udp_addr,
2430  udp_addr_len,
2432  s = udp_plugin_lookup_session (plugin,
2433  address);
2434  if (NULL == s)
2435  {
2437  "UDP session of address %s for ACK not found\n",
2438  udp_address_to_string (plugin,
2439  address->address,
2440  address->address_length));
2441  GNUNET_HELLO_address_free (address);
2442  return;
2443  }
2444  if (NULL == s->frag_ctx)
2445  {
2447  "Fragmentation context of address %s for ACK (%s) not found\n",
2448  udp_address_to_string (plugin,
2449  address->address,
2450  address->address_length),
2452  GNUNET_HELLO_address_free (address);
2453  return;
2454  }
2455  GNUNET_HELLO_address_free (address);
2456 
2457  /* evaluate flow delay: how long should we wait between messages? */
2458  if (UINT32_MAX == ntohl (udp_ack->delay))
2459  {
2460  /* Other peer asked for us to terminate the session */
2462  "Asked to disconnect UDP session of %s\n",
2463  GNUNET_i2s (&udp_ack->sender));
2464  udp_disconnect_session (plugin,
2465  s);
2466  return;
2467  }
2468  flow_delay.rel_value_us = (uint64_t) ntohl (udp_ack->delay);
2469  if (flow_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
2471  "We received a sending delay of %s for %s\n",
2473  GNUNET_YES),
2474  GNUNET_i2s (&udp_ack->sender));
2475  else
2477  "We received a sending delay of %s for %s\n",
2479  GNUNET_YES),
2480  GNUNET_i2s (&udp_ack->sender));
2481  /* Flow delay is for the reassembled packet, however, our delay
2482  is per packet, so we need to adjust: */
2483  s->flow_delay_from_other_peer = flow_delay;
2484 
2485  /* Handle ACK */
2486  if (GNUNET_OK !=
2488  ack))
2489  {
2491  "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
2492  (unsigned int) ntohs (msg->size),
2493  GNUNET_i2s (&udp_ack->sender),
2494  udp_address_to_string (plugin,
2495  udp_addr,
2496  udp_addr_len));
2497  /* Expect more ACKs to arrive */
2498  return;
2499  }
2500 
2501  /* Remove fragmented message after successful sending */
2503  "Message from %s at %s full ACK'ed\n",
2504  GNUNET_i2s (&udp_ack->sender),
2505  udp_address_to_string (plugin,
2506  udp_addr,
2507  udp_addr_len));
2509  GNUNET_OK);
2510 }
2511 
2512 
2521 static int
2523  const struct GNUNET_MessageHeader *hdr)
2524 {
2525  struct GNUNET_ATS_Session *session = cls;
2526  struct Plugin *plugin = session->plugin;
2527 
2528  if (GNUNET_YES == session->in_destroy)
2529  return GNUNET_OK;
2530  reschedule_session_timeout (session);
2531  session->flow_delay_for_other_peer
2532  = plugin->env->receive (plugin->env->cls,
2533  session->address,
2534  session,
2535  hdr);
2536  return GNUNET_OK;
2537 }
2538 
2539 
2548 static int
2550  const struct GNUNET_PeerIdentity *key,
2551  void *value)
2552 {
2553  struct Plugin *plugin = cls;
2554 
2555  udp_disconnect_session (plugin,
2556  value);
2557  return GNUNET_OK;
2558 }
2559 
2560 
2569 static void
2570 udp_disconnect (void *cls,
2571  const struct GNUNET_PeerIdentity *target)
2572 {
2573  struct Plugin *plugin = cls;
2574 
2576  "Disconnecting from peer `%s'\n",
2577  GNUNET_i2s (target));
2579  target,
2581  plugin);
2582 }
2583 
2584 
2590 static void
2591 session_timeout (void *cls)
2592 {
2593  struct GNUNET_ATS_Session *s = cls;
2594  struct Plugin *plugin = s->plugin;
2595  struct GNUNET_TIME_Relative left;
2596 
2597  s->timeout_task = NULL;
2599  if (left.rel_value_us > 0)
2600  {
2601  /* not actually our turn yet, but let's at least update
2602  the monitor, it may think we're about to die ... */
2604  s,
2607  &session_timeout,
2608  s);
2609  return;
2610  }
2612  "Session %p was idle for %s, disconnecting\n",
2613  s,
2615  GNUNET_YES));
2616  /* call session destroy function */
2617  udp_disconnect_session (plugin,
2618  s);
2619 }
2620 
2621 
2633 static struct GNUNET_ATS_Session *
2635  const struct GNUNET_HELLO_Address *address,
2636  enum GNUNET_NetworkType network_type)
2637 {
2638  struct Plugin *plugin = cls;
2639  struct GNUNET_ATS_Session *s;
2640 
2641  s = GNUNET_new (struct GNUNET_ATS_Session);
2643  s);
2644  s->plugin = plugin;
2645  s->address = GNUNET_HELLO_address_copy (address);
2646  s->target = address->peer;
2649  250);
2655  &session_timeout,
2656  s);
2657  s->scope = network_type;
2658 
2660  "Creating new session %p for peer `%s' address `%s'\n",
2661  s,
2662  GNUNET_i2s (&address->peer),
2663  udp_address_to_string (plugin,
2664  address->address,
2665  address->address_length));
2668  &s->target,
2669  s,
2671  GNUNET_STATISTICS_set (plugin->env->stats,
2672  "# UDP sessions active",
2674  GNUNET_NO);
2675  notify_session_monitor (plugin,
2676  s,
2678  return s;
2679 }
2680 
2681 
2690 static struct GNUNET_ATS_Session *
2692  const struct GNUNET_HELLO_Address *address)
2693 {
2694  struct Plugin *plugin = cls;
2695  struct GNUNET_ATS_Session *s;
2696  enum GNUNET_NetworkType network_type = GNUNET_NT_UNSPECIFIED;
2697  const struct IPv4UdpAddress *udp_v4;
2698  const struct IPv6UdpAddress *udp_v6;
2699 
2700  if (NULL == address)
2701  {
2702  GNUNET_break (0);
2703  return NULL;
2704  }
2705  if ( (address->address_length != sizeof(struct IPv4UdpAddress)) &&
2706  (address->address_length != sizeof(struct IPv6UdpAddress)) )
2707  {
2708  GNUNET_break_op (0);
2709  return NULL;
2710  }
2711  if (NULL != (s = udp_plugin_lookup_session (cls,
2712  address)))
2713  return s;
2714 
2715  /* need to create new session */
2716  if (sizeof (struct IPv4UdpAddress) == address->address_length)
2717  {
2718  struct sockaddr_in v4;
2719 
2720  udp_v4 = (const struct IPv4UdpAddress *) address->address;
2721  memset (&v4, '\0', sizeof (v4));
2722  v4.sin_family = AF_INET;
2723 #if HAVE_SOCKADDR_IN_SIN_LEN
2724  v4.sin_len = sizeof (struct sockaddr_in);
2725 #endif
2726  v4.sin_port = udp_v4->u4_port;
2727  v4.sin_addr.s_addr = udp_v4->ipv4_addr;
2728  network_type = plugin->env->get_address_type (plugin->env->cls,
2729  (const struct sockaddr *) &v4,
2730  sizeof (v4));
2731  }
2732  if (sizeof (struct IPv6UdpAddress) == address->address_length)
2733  {
2734  struct sockaddr_in6 v6;
2735 
2736  udp_v6 = (const struct IPv6UdpAddress *) address->address;
2737  memset (&v6, '\0', sizeof (v6));
2738  v6.sin6_family = AF_INET6;
2739 #if HAVE_SOCKADDR_IN_SIN_LEN
2740  v6.sin6_len = sizeof (struct sockaddr_in6);
2741 #endif
2742  v6.sin6_port = udp_v6->u6_port;
2743  v6.sin6_addr = udp_v6->ipv6_addr;
2744  network_type = plugin->env->get_address_type (plugin->env->cls,
2745  (const struct sockaddr *) &v6,
2746  sizeof (v6));
2747  }
2748  GNUNET_break (GNUNET_NT_UNSPECIFIED != network_type);
2749  return udp_plugin_create_session (cls,
2750  address,
2751  network_type);
2752 }
2753 
2754 
2764 static void
2766  const struct UDPMessage *msg,
2767  const union UdpAddress *udp_addr,
2768  size_t udp_addr_len,
2769  enum GNUNET_NetworkType network_type)
2770 {
2771  struct GNUNET_ATS_Session *s;
2772  struct GNUNET_HELLO_Address *address;
2773 
2774  GNUNET_break (GNUNET_NT_UNSPECIFIED != network_type);
2775  if (0 != ntohl (msg->reserved))
2776  {
2777  GNUNET_break_op(0);
2778  return;
2779  }
2780  if (ntohs (msg->header.size)
2781  < sizeof(struct GNUNET_MessageHeader) + sizeof(struct UDPMessage))
2782  {
2783  GNUNET_break_op(0);
2784  return;
2785  }
2786 
2787  address = GNUNET_HELLO_address_allocate (&msg->sender,
2788  PLUGIN_NAME,
2789  udp_addr,
2790  udp_addr_len,
2792  if (NULL ==
2793  (s = udp_plugin_lookup_session (plugin,
2794  address)))
2795  {
2796  s = udp_plugin_create_session (plugin,
2797  address,
2798  network_type);
2799  plugin->env->session_start (plugin->env->cls,
2800  address,
2801  s,
2802  s->scope);
2803  notify_session_monitor (plugin,
2804  s,
2806  }
2807  GNUNET_free (address);
2808 
2809  s->rc++;
2811  (const char *) &msg[1],
2812  ntohs (msg->header.size) - sizeof(struct UDPMessage),
2813  GNUNET_YES,
2814  GNUNET_NO);
2815  s->rc--;
2816  if ( (0 == s->rc) &&
2817  (GNUNET_YES == s->in_destroy) )
2818  free_session (s);
2819 }
2820 
2821 
2828 static void
2830  const struct GNUNET_MessageHeader *msg)
2831 {
2832  struct DefragContext *dc = cls;
2833  const struct UDPMessage *um;
2834 
2835  if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE)
2836  {
2837  GNUNET_break_op (0);
2838  return;
2839  }
2840  if (ntohs (msg->size) < sizeof(struct UDPMessage))
2841  {
2842  GNUNET_break_op (0);
2843  return;
2844  }
2845  um = (const struct UDPMessage *) msg;
2846  dc->sender = um->sender;
2847  dc->have_sender = GNUNET_YES;
2849  um,
2850  dc->udp_addr,
2851  dc->udp_addr_len,
2852  dc->network_type);
2853 }
2854 
2855 
2865 static void
2866 ack_message_sent (void *cls,
2867  struct UDP_MessageWrapper *udpw,
2868  int result)
2869 {
2870  struct Plugin *plugin = cls;
2871 
2872  if (GNUNET_OK == result)
2873  {
2874  GNUNET_STATISTICS_update (plugin->env->stats,
2875  "# UDP, ACK messages sent",
2876  1,
2877  GNUNET_NO);
2878  }
2879  else
2880  {
2881  GNUNET_STATISTICS_update (plugin->env->stats,
2882  "# UDP, ACK transmissions failed",
2883  1,
2884  GNUNET_NO);
2885  }
2886 }
2887 
2888 
2896 static void
2897 ack_proc (void *cls,
2898  uint32_t id,
2899  const struct GNUNET_MessageHeader *msg)
2900 {
2901  struct DefragContext *rc = cls;
2902  struct Plugin *plugin = rc->plugin;
2903  size_t msize = sizeof(struct UDP_ACK_Message) + ntohs (msg->size);
2904  struct UDP_ACK_Message *udp_ack;
2905  uint32_t delay;
2906  struct UDP_MessageWrapper *udpw;
2907  struct GNUNET_ATS_Session *s;
2908  struct GNUNET_HELLO_Address *address;
2909 
2910  if (GNUNET_NO == rc->have_sender)
2911  {
2912  /* tried to defragment but never succeeded, hence will not ACK */
2913  /* This can happen if we just lost msgs */
2914  GNUNET_STATISTICS_update (plugin->env->stats,
2915  "# UDP, fragments discarded without ACK",
2916  1,
2917  GNUNET_NO);
2918  return;
2919  }
2920  address = GNUNET_HELLO_address_allocate (&rc->sender,
2921  PLUGIN_NAME,
2922  rc->udp_addr,
2923  rc->udp_addr_len,
2925  s = udp_plugin_lookup_session (plugin,
2926  address);
2927  GNUNET_HELLO_address_free (address);
2928  if (NULL == s)
2929  {
2931  "Trying to transmit ACK to peer `%s' but no session found!\n",
2932  udp_address_to_string (plugin,
2933  rc->udp_addr,
2934  rc->udp_addr_len));
2937  GNUNET_free (rc);
2938  GNUNET_STATISTICS_update (plugin->env->stats,
2939  "# UDP, ACK transmissions failed",
2940  1,
2941  GNUNET_NO);
2942  return;
2943  }
2944  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us ==
2946  delay = UINT32_MAX;
2947  else if (s->flow_delay_for_other_peer.rel_value_us < UINT32_MAX)
2949  else
2950  delay = UINT32_MAX - 1; /* largest value we can communicate */
2952  "Sending ACK to `%s' including delay of %s\n",
2953  udp_address_to_string (plugin,
2954  rc->udp_addr,
2955  rc->udp_addr_len),
2957  GNUNET_YES));
2958  udpw = GNUNET_malloc (sizeof (struct UDP_MessageWrapper) + msize);
2959  udpw->msg_size = msize;
2960  udpw->payload_size = 0;
2961  udpw->session = s;
2964  udpw->msg_buf = (char *) &udpw[1];
2965  udpw->qc = &ack_message_sent;
2966  udpw->qc_cls = plugin;
2967  udp_ack = (struct UDP_ACK_Message *) udpw->msg_buf;
2968  udp_ack->header.size = htons ((uint16_t) msize);
2970  udp_ack->delay = htonl (delay);
2971  udp_ack->sender = *plugin->env->my_identity;
2972  GNUNET_memcpy (&udp_ack[1],
2973  msg,
2974  ntohs (msg->size));
2975  enqueue (plugin,
2976  udpw);
2977  notify_session_monitor (plugin,
2978  s,
2980  if (s->address->address_length == sizeof (struct IPv4UdpAddress))
2981  schedule_select_v4 (plugin);
2982  else
2983  schedule_select_v6 (plugin);
2984 }
2985 
2986 
2996 static void
2998  const struct GNUNET_MessageHeader *msg,
2999  const union UdpAddress *udp_addr,
3000  size_t udp_addr_len,
3001  enum GNUNET_NetworkType network_type)
3002 {
3003  struct DefragContext *d_ctx;
3004  struct GNUNET_TIME_Absolute now;
3005  struct FindReceiveContext frc;
3006 
3007  frc.rc = NULL;
3008  frc.udp_addr = udp_addr;
3009  frc.udp_addr_len = udp_addr_len;
3010 
3011  /* Lookup existing receive context for this address */
3014  &frc);
3015  now = GNUNET_TIME_absolute_get ();
3016  d_ctx = frc.rc;
3017 
3018  if (NULL == d_ctx)
3019  {
3020  /* Create a new defragmentation context */
3021  d_ctx = GNUNET_malloc (sizeof (struct DefragContext) + udp_addr_len);
3022  GNUNET_memcpy (&d_ctx[1],
3023  udp_addr,
3024  udp_addr_len);
3025  d_ctx->udp_addr = (const union UdpAddress *) &d_ctx[1];
3026  d_ctx->udp_addr_len = udp_addr_len;
3027  d_ctx->network_type = network_type;
3028  d_ctx->plugin = plugin;
3029  d_ctx->defrag = GNUNET_DEFRAGMENT_context_create (plugin->env->stats,
3030  UDP_MTU,
3032  d_ctx,
3034  &ack_proc);
3036  d_ctx,
3039  "Created new defragmentation context for %u-byte fragment from `%s'\n",
3040  (unsigned int) ntohs (msg->size),
3041  udp_address_to_string (plugin,
3042  udp_addr,
3043  udp_addr_len));
3044  }
3045  else
3046  {
3048  "Found existing defragmentation context for %u-byte fragment from `%s'\n",
3049  (unsigned int) ntohs (msg->size),
3050  udp_address_to_string (plugin,
3051  udp_addr,
3052  udp_addr_len));
3053  }
3054 
3055  if (GNUNET_OK ==
3057  msg))
3058  {
3059  /* keep this 'rc' from expiring */
3062  }
3065  {
3066  /* remove 'rc' that was inactive the longest */
3068  GNUNET_assert (NULL != d_ctx);
3070  GNUNET_free (d_ctx);
3071  GNUNET_STATISTICS_update (plugin->env->stats,
3072  "# UDP, Defragmentations aborted",
3073  1,
3074  GNUNET_NO);
3075  }
3076 }
3077 
3078 
3085 static void
3087  struct GNUNET_NETWORK_Handle *rsock)
3088 {
3089  socklen_t fromlen;
3090  struct sockaddr_storage addr;
3091  char buf[65536] GNUNET_ALIGN;
3092  ssize_t size;
3093  const struct GNUNET_MessageHeader *msg;
3094  struct IPv4UdpAddress v4;
3095  struct IPv6UdpAddress v6;
3096  const struct sockaddr *sa;
3097  const struct sockaddr_in *sa4;
3098  const struct sockaddr_in6 *sa6;
3099  const union UdpAddress *int_addr;
3100  size_t int_addr_len;
3101  enum GNUNET_NetworkType network_type;
3102 
3103  fromlen = sizeof (addr);
3104  memset (&addr,
3105  0,
3106  sizeof(addr));
3107  size = GNUNET_NETWORK_socket_recvfrom (rsock,
3108  buf,
3109  sizeof (buf),
3110  (struct sockaddr *) &addr,
3111  &fromlen);
3112  sa = (const struct sockaddr *) &addr;
3113 #if MINGW
3114  /* On SOCK_DGRAM UDP sockets recvfrom might fail with a
3115  * WSAECONNRESET error to indicate that previous sendto() (yes, sendto!)
3116  * on this socket has failed.
3117  * Quote from MSDN:
3118  * WSAECONNRESET - The virtual circuit was reset by the remote side
3119  * executing a hard or abortive close. The application should close
3120  * the socket; it is no longer usable. On a UDP-datagram socket this
3121  * error indicates a previous send operation resulted in an ICMP Port
3122  * Unreachable message.
3123  */
3124  if ( (-1 == size) &&
3125  (ECONNRESET == errno) )
3126  return;
3127 #endif
3128  if (-1 == size)
3129  {
3131  "UDP failed to receive data: %s\n",
3132  STRERROR (errno));
3133  /* Connection failure or something. Not a protocol violation. */
3134  return;
3135  }
3136 
3137  /* Check if this is a STUN packet */
3138  if (GNUNET_NO !=
3140  (const struct sockaddr *) &addr,
3141  fromlen,
3142  buf,
3143  size))
3144  return; /* was STUN, do not process further */
3145 
3146  if (size < sizeof(struct GNUNET_MessageHeader))
3147  {
3149  "UDP got %u bytes from %s, which is not enough for a GNUnet message header\n",
3150  (unsigned int ) size,
3151  GNUNET_a2s (sa,
3152  fromlen));
3153  /* _MAY_ be a connection failure (got partial message) */
3154  /* But it _MAY_ also be that the other side uses non-GNUnet protocol. */
3155  GNUNET_break_op (0);
3156  return;
3157  }
3158 
3159  msg = (const struct GNUNET_MessageHeader *) buf;
3161  "UDP received %u-byte message from `%s' type %u\n",
3162  (unsigned int) size,
3163  GNUNET_a2s (sa,
3164  fromlen),
3165  ntohs (msg->type));
3166  if (size != ntohs (msg->size))
3167  {
3169  "UDP malformed message (size %u) header from %s\n",
3170  (unsigned int) size,
3171  GNUNET_a2s (sa,
3172  fromlen));
3173  GNUNET_break_op (0);
3174  return;
3175  }
3176  GNUNET_STATISTICS_update (plugin->env->stats,
3177  "# UDP, total bytes received",
3178  size,
3179  GNUNET_NO);
3180  network_type = plugin->env->get_address_type (plugin->env->cls,
3181  sa,
3182  fromlen);
3183  switch (sa->sa_family)
3184  {
3185  case AF_INET:
3186  sa4 = (const struct sockaddr_in *) &addr;
3187  v4.options = 0;
3188  v4.ipv4_addr = sa4->sin_addr.s_addr;
3189  v4.u4_port = sa4->sin_port;
3190  int_addr = (union UdpAddress *) &v4;
3191  int_addr_len = sizeof (v4);
3192  break;
3193  case AF_INET6:
3194  sa6 = (const struct sockaddr_in6 *) &addr;
3195  v6.options = 0;
3196  v6.ipv6_addr = sa6->sin6_addr;
3197  v6.u6_port = sa6->sin6_port;
3198  int_addr = (union UdpAddress *) &v6;
3199  int_addr_len = sizeof (v6);
3200  break;
3201  default:
3202  GNUNET_break (0);
3203  return;
3204  }
3205 
3206  switch (ntohs (msg->type))
3207  {
3210  udp_broadcast_receive (plugin,
3211  buf,
3212  size,
3213  int_addr,
3214  int_addr_len,
3215  network_type);
3216  return;
3218  if (ntohs (msg->size) < sizeof(struct UDPMessage))
3219  {
3220  GNUNET_break_op(0);
3221  return;
3222  }
3223  process_udp_message (plugin,
3224  (const struct UDPMessage *) msg,
3225  int_addr,
3226  int_addr_len,
3227  network_type);
3228  return;
3230  read_process_ack (plugin,
3231  msg,
3232  int_addr,
3233  int_addr_len);
3234  return;
3236  read_process_fragment (plugin,
3237  msg,
3238  int_addr,
3239  int_addr_len,
3240  network_type);
3241  return;
3242  default:
3243  GNUNET_break_op(0);
3244  return;
3245  }
3246 }
3247 
3248 
3258 static struct UDP_MessageWrapper *
3260  struct GNUNET_NETWORK_Handle *sock)
3261 {
3262  struct UDP_MessageWrapper *udpw;
3263  struct GNUNET_TIME_Relative remaining;
3264  struct GNUNET_ATS_Session *session;
3265  int removed;
3266 
3267  removed = GNUNET_NO;
3268  udpw = (sock == plugin->sockv4)
3269  ? plugin->ipv4_queue_head
3270  : plugin->ipv6_queue_head;
3271  while (NULL != udpw)
3272  {
3273  session = udpw->session;
3274  /* Find messages with timeout */
3275  remaining = GNUNET_TIME_absolute_get_remaining (udpw->timeout);
3276  if (GNUNET_TIME_UNIT_ZERO.rel_value_us == remaining.rel_value_us)
3277  {
3278  /* Message timed out */
3279  removed = GNUNET_YES;
3280  dequeue (plugin,
3281  udpw);
3282  udpw->qc (udpw->qc_cls,
3283  udpw,
3284  GNUNET_SYSERR);
3285  GNUNET_free (udpw);
3286 
3287  if (sock == plugin->sockv4)
3288  {
3289  udpw = plugin->ipv4_queue_head;
3290  }
3291  else if (sock == plugin->sockv6)
3292  {
3293  udpw = plugin->ipv6_queue_head;
3294  }
3295  else
3296  {
3297  GNUNET_break (0); /* should never happen */
3298  udpw = NULL;
3299  }
3300  GNUNET_STATISTICS_update (plugin->env->stats,
3301  "# messages discarded due to timeout",
3302  1,
3303  GNUNET_NO);
3304  }
3305  else
3306  {
3307  /* Message did not time out, check transmission time */
3309  if (0 == remaining.rel_value_us)
3310  {
3311  /* this message is not delayed */
3313  "Message for peer `%s' (%u bytes) is not delayed \n",
3314  GNUNET_i2s (&udpw->session->target),
3315  udpw->payload_size);
3316  break; /* Found message to send, break */
3317  }
3318  else
3319  {
3320  /* Message is delayed, try next */
3322  "Message for peer `%s' (%u bytes) is delayed for %s\n",
3323  GNUNET_i2s (&udpw->session->target),
3324  udpw->payload_size,
3326  GNUNET_YES));
3327  udpw = udpw->next;
3328  }
3329  }
3330  }
3331  if (GNUNET_YES == removed)
3332  notify_session_monitor (session->plugin,
3333  session,
3335  return udpw;
3336 }
3337 
3338 
3348 static void
3350  const struct sockaddr *sa,
3351  socklen_t slen,
3352  int error)
3353 {
3354  enum GNUNET_NetworkType type;
3355 
3356  type = plugin->env->get_address_type (plugin->env->cls,
3357  sa,
3358  slen);
3359  if ( ( (GNUNET_NT_LAN == type) ||
3360  (GNUNET_NT_WAN == type) ) &&
3361  ( (ENETUNREACH == errno) ||
3362  (ENETDOWN == errno) ) )
3363  {
3364  if (slen == sizeof (struct sockaddr_in))
3365  {
3366  /* IPv4: "Network unreachable" or "Network down"
3367  *
3368  * This indicates we do not have connectivity
3369  */
3371  _("UDP could not transmit message to `%s': "
3372  "Network seems down, please check your network configuration\n"),
3373  GNUNET_a2s (sa,
3374  slen));
3375  }
3376  if (slen == sizeof (struct sockaddr_in6))
3377  {
3378  /* IPv6: "Network unreachable" or "Network down"
3379  *
3380  * This indicates that this system is IPv6 enabled, but does not
3381  * have a valid global IPv6 address assigned or we do not have
3382  * connectivity
3383  */
3385  _("UDP could not transmit IPv6 message! "
3386  "Please check your network configuration and disable IPv6 if your "
3387  "connection does not have a global IPv6 address\n"));
3388  }
3389  }
3390  else
3391  {
3393  "UDP could not transmit message to `%s': `%s'\n",
3394  GNUNET_a2s (sa,
3395  slen),
3396  STRERROR (error));
3397  }
3398 }
3399 
3400 
3408 static void
3410  struct GNUNET_NETWORK_Handle *sock)
3411 {
3412  ssize_t sent;
3413  socklen_t slen;
3414  const struct sockaddr *a;
3415  const struct IPv4UdpAddress *u4;
3416  struct sockaddr_in a4;
3417  const struct IPv6UdpAddress *u6;
3418  struct sockaddr_in6 a6;
3419  struct UDP_MessageWrapper *udpw;
3420 
3421  /* Find message(s) to send */
3422  while (NULL != (udpw = remove_timeout_messages_and_select (plugin,
3423  sock)))
3424  {
3425  if (sizeof (struct IPv4UdpAddress) == udpw->session->address->address_length)
3426  {
3427  u4 = udpw->session->address->address;
3428  memset (&a4,
3429  0,
3430  sizeof(a4));
3431  a4.sin_family = AF_INET;
3432 #if HAVE_SOCKADDR_IN_SIN_LEN
3433  a4.sin_len = sizeof (a4);
3434 #endif
3435  a4.sin_port = u4->u4_port;
3436  a4.sin_addr.s_addr = u4->ipv4_addr;
3437  a = (const struct sockaddr *) &a4;
3438  slen = sizeof (a4);
3439  }
3440  else if (sizeof (struct IPv6UdpAddress) == udpw->session->address->address_length)
3441  {
3442  u6 = udpw->session->address->address;
3443  memset (&a6,
3444  0,
3445  sizeof(a6));
3446  a6.sin6_family = AF_INET6;
3447 #if HAVE_SOCKADDR_IN_SIN_LEN
3448  a6.sin6_len = sizeof (a6);
3449 #endif
3450  a6.sin6_port = u6->u6_port;
3451  a6.sin6_addr = u6->ipv6_addr;
3452  a = (const struct sockaddr *) &a6;
3453  slen = sizeof (a6);
3454  }
3455  else
3456  {
3457  GNUNET_break (0);
3458  dequeue (plugin,
3459  udpw);
3460  udpw->qc (udpw->qc_cls,
3461  udpw,
3462  GNUNET_SYSERR);
3463  notify_session_monitor (plugin,
3464  udpw->session,
3466  GNUNET_free (udpw);
3467  continue;
3468  }
3469  sent = GNUNET_NETWORK_socket_sendto (sock,
3470  udpw->msg_buf,
3471  udpw->msg_size,
3472  a,
3473  slen);
3476  udpw->session->last_transmit_time);
3477  dequeue (plugin,
3478  udpw);
3479  if (GNUNET_SYSERR == sent)
3480  {
3481  /* Failure */
3482  analyze_send_error (plugin,
3483  a,
3484  slen,
3485  errno);
3486  udpw->qc (udpw->qc_cls,
3487  udpw,
3488  GNUNET_SYSERR);
3489  GNUNET_STATISTICS_update (plugin->env->stats,
3490  "# UDP, total, bytes, sent, failure",
3491  sent,
3492  GNUNET_NO);
3493  GNUNET_STATISTICS_update (plugin->env->stats,
3494  "# UDP, total, messages, sent, failure",
3495  1,
3496  GNUNET_NO);
3497  }
3498  else
3499  {
3500  /* Success */
3502  "UDP transmitted %u-byte message to `%s' `%s' (%d: %s)\n",
3503  (unsigned int) (udpw->msg_size),
3504  GNUNET_i2s (&udpw->session->target),
3505  GNUNET_a2s (a,
3506  slen),
3507  (int ) sent,
3508  (sent < 0) ? STRERROR (errno) : "ok");
3509  GNUNET_STATISTICS_update (plugin->env->stats,
3510  "# UDP, total, bytes, sent, success",
3511  sent,
3512  GNUNET_NO);
3513  GNUNET_STATISTICS_update (plugin->env->stats,
3514  "# UDP, total, messages, sent, success",
3515  1,
3516  GNUNET_NO);
3517  if (NULL != udpw->frag_ctx)
3518  udpw->frag_ctx->on_wire_size += udpw->msg_size;
3519  udpw->qc (udpw->qc_cls,
3520  udpw,
3521  GNUNET_OK);
3522  }
3523  notify_session_monitor (plugin,
3524  udpw->session,
3526  GNUNET_free (udpw);
3527  }
3528 }
3529 
3530 
3531 /* ***************** Event loop (part 2) *************** */
3532 
3533 
3541 static void
3543 {
3544  struct Plugin *plugin = cls;
3545  const struct GNUNET_SCHEDULER_TaskContext *tc;
3546 
3547  plugin->select_task_v4 = NULL;
3548  if (NULL == plugin->sockv4)
3549  return;
3551  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
3553  plugin->sockv4)))
3554  udp_select_read (plugin,
3555  plugin->sockv4);
3556  udp_select_send (plugin,
3557  plugin->sockv4);
3558  schedule_select_v4 (plugin);
3559 }
3560 
3561 
3569 static void
3571 {
3572  struct Plugin *plugin = cls;
3573  const struct GNUNET_SCHEDULER_TaskContext *tc;
3574 
3575  plugin->select_task_v6 = NULL;
3576  if (NULL == plugin->sockv6)
3577  return;
3579  if ( (0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
3581  plugin->sockv6)) )
3582  udp_select_read (plugin,
3583  plugin->sockv6);
3584 
3585  udp_select_send (plugin,
3586  plugin->sockv6);
3587  schedule_select_v6 (plugin);
3588 }
3589 
3590 
3591 /* ******************* Initialization *************** */
3592 
3593 
3602 static unsigned int
3604  const struct sockaddr_in6 *bind_v6,
3605  const struct sockaddr_in *bind_v4)
3606 {
3607  int tries;
3608  unsigned int sockets_created = 0;
3609  struct sockaddr_in6 server_addrv6;
3610  struct sockaddr_in server_addrv4;
3611  const struct sockaddr *server_addr;
3612  const struct sockaddr *addrs[2];
3613  socklen_t addrlens[2];
3614  socklen_t addrlen;
3615  int eno;
3616 
3617  /* Create IPv6 socket */
3618  eno = EINVAL;
3619  if (GNUNET_YES == plugin->enable_ipv6)
3620  {
3621  plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6,
3622  SOCK_DGRAM,
3623  0);
3624  if (NULL == plugin->sockv6)
3625  {
3627  _("Disabling IPv6 since it is not supported on this system!\n"));
3628  plugin->enable_ipv6 = GNUNET_NO;
3629  }
3630  else
3631  {
3632  memset (&server_addrv6,
3633  0,
3634  sizeof(struct sockaddr_in6));
3635 #if HAVE_SOCKADDR_IN_SIN_LEN
3636  server_addrv6.sin6_len = sizeof (struct sockaddr_in6);
3637 #endif
3638  server_addrv6.sin6_family = AF_INET6;
3639  if (NULL != bind_v6)
3640  server_addrv6.sin6_addr = bind_v6->sin6_addr;
3641  else
3642  server_addrv6.sin6_addr = in6addr_any;
3643 
3644  if (0 == plugin->port) /* autodetect */
3645  server_addrv6.sin6_port
3647  33537)
3648  + 32000);
3649  else
3650  server_addrv6.sin6_port = htons (plugin->port);
3651  addrlen = sizeof (struct sockaddr_in6);
3652  server_addr = (const struct sockaddr *) &server_addrv6;
3653 
3654  tries = 0;
3655  while (tries < 10)
3656  {
3658  "Binding to IPv6 `%s'\n",
3659  GNUNET_a2s (server_addr,
3660  addrlen));
3661  /* binding */
3662  if (GNUNET_OK ==
3664  server_addr,
3665  addrlen))
3666  break;
3667  eno = errno;
3668  if (0 != plugin->port)
3669  {
3670  tries = 10; /* fail immediately */
3671  break; /* bind failed on specific port */
3672  }
3673  /* autodetect */
3674  server_addrv6.sin6_port
3676  33537)
3677  + 32000);
3678  tries++;
3679  }
3680  if (tries >= 10)
3681  {
3683  plugin->enable_ipv6 = GNUNET_NO;
3684  plugin->sockv6 = NULL;
3685  }
3686  else
3687  {
3688  plugin->port = ntohs (server_addrv6.sin6_port);
3689  }
3690  if (NULL != plugin->sockv6)
3691  {
3693  "IPv6 UDP socket created listinging at %s\n",
3694  GNUNET_a2s (server_addr,
3695  addrlen));
3696  addrs[sockets_created] = server_addr;
3697  addrlens[sockets_created] = addrlen;
3698  sockets_created++;
3699  }
3700  else
3701  {
3703  _("Failed to bind UDP socket to %s: %s\n"),
3704  GNUNET_a2s (server_addr,
3705  addrlen),
3706  STRERROR (eno));
3707  }
3708  }
3709  }
3710 
3711  /* Create IPv4 socket */
3712  eno = EINVAL;
3713  plugin->sockv4 = GNUNET_NETWORK_socket_create (PF_INET,
3714  SOCK_DGRAM,
3715  0);
3716  if (NULL == plugin->sockv4)
3717  {
3719  "socket");
3721  _("Disabling IPv4 since it is not supported on this system!\n"));
3722  plugin->enable_ipv4 = GNUNET_NO;
3723  }
3724  else
3725  {
3726  memset (&server_addrv4,
3727  0,
3728  sizeof(struct sockaddr_in));
3729 #if HAVE_SOCKADDR_IN_SIN_LEN
3730  server_addrv4.sin_len = sizeof (struct sockaddr_in);
3731 #endif
3732  server_addrv4.sin_family = AF_INET;
3733  if (NULL != bind_v4)
3734  server_addrv4.sin_addr = bind_v4->sin_addr;
3735  else
3736  server_addrv4.sin_addr.s_addr = INADDR_ANY;
3737 
3738  if (0 == plugin->port)
3739  /* autodetect */
3740  server_addrv4.sin_port
3742  33537)
3743  + 32000);
3744  else
3745  server_addrv4.sin_port = htons (plugin->port);
3746 
3747  addrlen = sizeof (struct sockaddr_in);
3748  server_addr = (const struct sockaddr *) &server_addrv4;
3749 
3750  tries = 0;
3751  while (tries < 10)
3752  {
3754  "Binding to IPv4 `%s'\n",
3755  GNUNET_a2s (server_addr,
3756  addrlen));
3757 
3758  /* binding */
3759  if (GNUNET_OK ==
3761  server_addr,
3762  addrlen))
3763  break;
3764  eno = errno;
3765  if (0 != plugin->port)
3766  {
3767  tries = 10; /* fail */
3768  break; /* bind failed on specific port */
3769  }
3770 
3771  /* autodetect */
3772  server_addrv4.sin_port
3774  33537)
3775  + 32000);
3776  tries++;
3777  }
3778  if (tries >= 10)
3779  {
3781  plugin->enable_ipv4 = GNUNET_NO;
3782  plugin->sockv4 = NULL;
3783  }
3784  else
3785  {
3786  plugin->port = ntohs (server_addrv4.sin_port);
3787  }
3788 
3789  if (NULL != plugin->sockv4)
3790  {
3792  "IPv4 socket created on port %s\n",
3793  GNUNET_a2s (server_addr,
3794  addrlen));
3795  addrs[sockets_created] = server_addr;
3796  addrlens[sockets_created] = addrlen;
3797  sockets_created++;
3798  }
3799  else
3800  {
3802  _("Failed to bind UDP socket to %s: %s\n"),
3803  GNUNET_a2s (server_addr,
3804  addrlen),
3805  STRERROR (eno));
3806  }
3807  }
3808 
3809  if (0 == sockets_created)
3810  {
3812  _("Failed to open UDP sockets\n"));
3813  return 0; /* No sockets created, return */
3814  }
3815  schedule_select_v4 (plugin);
3816  schedule_select_v6 (plugin);
3817  plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
3818  "transport-udp",
3819  IPPROTO_UDP,
3820  sockets_created,
3821  addrs,
3822  addrlens,
3824  NULL,
3825  plugin);
3826  return sockets_created;
3827 }
3828 
3829 
3837 void *
3839 {
3842  struct Plugin *p;
3843  unsigned long long port;
3844  unsigned long long aport;
3845  unsigned long long udp_max_bps;
3846  int enable_v6;
3847  int enable_broadcasting;
3848  int enable_broadcasting_recv;
3849  char *bind4_address;
3850  char *bind6_address;
3851  struct GNUNET_TIME_Relative interval;
3852  struct sockaddr_in server_addrv4;
3853  struct sockaddr_in6 server_addrv6;
3854  unsigned int res;
3855  int have_bind4;
3856  int have_bind6;
3857 
3858  if (NULL == env->receive)
3859  {
3860  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
3861  initialze the plugin or the API */
3863  api->cls = NULL;
3867  return api;
3868  }
3869 
3870  /* Get port number: port == 0 : autodetect a port,
3871  * > 0 : use this port, not given : 2086 default */
3872  if (GNUNET_OK !=
3874  "transport-udp",
3875  "PORT",
3876  &port))
3877  port = 2086;
3878  if (port > 65535)
3879  {
3881  "transport-udp",
3882  "PORT",
3883  _("must be in [0,65535]"));
3884  return NULL;
3885  }
3886  if (GNUNET_OK !=
3888  "transport-udp",
3889  "ADVERTISED_PORT",
3890  &aport))
3891  aport = port;
3892  if (aport > 65535)
3893  {
3895  "transport-udp",
3896  "ADVERTISED_PORT",
3897  _("must be in [0,65535]"));
3898  return NULL;
3899  }
3900 
3901  if (GNUNET_YES ==
3903  "nat",
3904  "DISABLEV6"))
3905  enable_v6 = GNUNET_NO;
3906  else
3907  enable_v6 = GNUNET_YES;
3908 
3909  have_bind4 = GNUNET_NO;
3910  memset (&server_addrv4,
3911  0,
3912  sizeof (server_addrv4));
3913  if (GNUNET_YES ==
3915  "transport-udp",
3916  "BINDTO",
3917  &bind4_address))
3918  {
3920  "Binding UDP plugin to specific address: `%s'\n",
3921  bind4_address);
3922  if (1 != inet_pton (AF_INET,
3923  bind4_address,
3924  &server_addrv4.sin_addr))
3925  {
3927  "transport-udp",
3928  "BINDTO",
3929  _("must be valid IPv4 address"));
3930  GNUNET_free (bind4_address);
3931  return NULL;
3932  }
3933  have_bind4 = GNUNET_YES;
3934  }
3935  GNUNET_free_non_null (bind4_address);
3936  have_bind6 = GNUNET_NO;
3937  memset (&server_addrv6,
3938  0,
3939  sizeof (server_addrv6));
3940  if (GNUNET_YES ==
3942  "transport-udp",
3943  "BINDTO6",
3944  &bind6_address))
3945  {
3947  "Binding udp plugin to specific address: `%s'\n",
3948  bind6_address);
3949  if (1 != inet_pton (AF_INET6,
3950  bind6_address,
3951  &server_addrv6.sin6_addr))
3952  {
3954  "transport-udp",
3955  "BINDTO6",
3956  _("must be valid IPv6 address"));
3957  GNUNET_free (bind6_address);
3958  return NULL;
3959  }
3960  have_bind6 = GNUNET_YES;
3961  }
3962  GNUNET_free_non_null (bind6_address);
3963 
3964  enable_broadcasting = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
3965  "transport-udp",
3966  "BROADCAST");
3967  if (enable_broadcasting == GNUNET_SYSERR)
3968  enable_broadcasting = GNUNET_NO;
3969 
3970  enable_broadcasting_recv = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
3971  "transport-udp",
3972  "BROADCAST_RECEIVE");
3973  if (enable_broadcasting_recv == GNUNET_SYSERR)
3974  enable_broadcasting_recv = GNUNET_YES;
3975 
3976  if (GNUNET_SYSERR ==
3978  "transport-udp",
3979  "BROADCAST_INTERVAL",
3980  &interval))
3981  {
3983  10);
3984  }
3985  if (GNUNET_OK !=
3987  "transport-udp",
3988  "MAX_BPS",
3989  &udp_max_bps))
3990  {
3991  /* 50 MB/s == infinity for practical purposes */
3992  udp_max_bps = 1024 * 1024 * 50;
3993  }
3994 
3995  p = GNUNET_new (struct Plugin);
3996  p->port = port;
3997  p->aport = aport;
3999  p->enable_ipv6 = enable_v6;
4000  p->enable_ipv4 = GNUNET_YES; /* default */
4001  p->enable_broadcasting = enable_broadcasting;
4002  p->enable_broadcasting_receiving = enable_broadcasting_recv;
4003  p->env = env;
4005  GNUNET_NO);
4008  NULL,
4009  NULL,
4010  GNUNET_BANDWIDTH_value_init ((uint32_t) udp_max_bps),
4011  30);
4012  res = setup_sockets (p,
4013  (GNUNET_YES == have_bind6) ? &server_addrv6 : NULL,
4014  (GNUNET_YES == have_bind4) ? &server_addrv4 : NULL);
4015  if ( (0 == res) ||
4016  ( (NULL == p->sockv4) &&
4017  (NULL == p->sockv6) ) )
4018  {
4020  _("Failed to create UDP network sockets\n"));
4023  if (NULL != p->nat)
4025  GNUNET_free (p);
4026  return NULL;
4027  }
4028 
4029  /* Setup broadcasting and receiving beacons */
4030  setup_broadcast (p,
4031  &server_addrv6,
4032  &server_addrv4);
4033 
4035  api->cls = p;
4044  api->send = &udp_plugin_send;
4049  return api;
4050 }
4051 
4052 
4063 static int
4065  struct GNUNET_CONTAINER_HeapNode *node,
4066  void *element,
4068 {
4069  struct DefragContext *d_ctx = element;
4070 
4073  GNUNET_free (d_ctx);
4074  return GNUNET_YES;
4075 }
4076 
4077 
4085 void *
4087 {
4088  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
4089  struct Plugin *plugin = api->cls;
4090  struct PrettyPrinterContext *cur;
4091  struct UDP_MessageWrapper *udpw;
4092 
4093  if (NULL == plugin)
4094  {
4095  GNUNET_free (api);
4096  return NULL;
4097  }
4098  stop_broadcast (plugin);
4099  if (NULL != plugin->select_task_v4)
4100  {
4102  plugin->select_task_v4 = NULL;
4103  }
4104  if (NULL != plugin->select_task_v6)
4105  {
4107  plugin->select_task_v6 = NULL;
4108  }
4109  if (NULL != plugin->sockv4)
4110  {
4113  plugin->sockv4 = NULL;
4114  }
4115  if (NULL != plugin->sockv6)
4116  {
4119  plugin->sockv6 = NULL;
4120  }
4121  if (NULL != plugin->nat)
4122  {
4123  GNUNET_NAT_unregister (plugin->nat);
4124  plugin->nat = NULL;
4125  }
4126  if (NULL != plugin->defrag_ctxs)
4127  {
4130  NULL);
4132  plugin->defrag_ctxs = NULL;
4133  }
4134  while (NULL != (udpw = plugin->ipv4_queue_head))
4135  {
4136  dequeue (plugin,
4137  udpw);
4138  udpw->qc (udpw->qc_cls,
4139  udpw,
4140  GNUNET_SYSERR);
4141  GNUNET_free (udpw);
4142  }
4143  while (NULL != (udpw = plugin->ipv6_queue_head))
4144  {
4145  dequeue (plugin,
4146  udpw);
4147  udpw->qc (udpw->qc_cls,
4148  udpw,
4149  GNUNET_SYSERR);
4150  GNUNET_free (udpw);
4151  }
4154  plugin);
4156 
4157  while (NULL != (cur = plugin->ppc_dll_head))
4158  {
4159  GNUNET_break (0);
4161  plugin->ppc_dll_tail,
4162  cur);
4164  if (NULL != cur->timeout_task)
4165  {
4167  cur->timeout_task = NULL;
4168  }
4169  GNUNET_free (cur);
4170  }
4171  GNUNET_free (plugin);
4172  GNUNET_free (api);
4173  return NULL;
4174 }
4175 
4176 /* end of plugin_transport_udp.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
size_t address_length
Number of bytes in address.
struct GNUNET_NAT_Handle * nat
NAT handle & address management.
struct GNUNET_TIME_Absolute last_transmit_time
What time did we last transmit?
size_t payload_size
Payload size of original message.
Session is being torn down and about to disappear.
static void ack_proc(void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
Transmit an acknowledgement.
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:746
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.
Local area network.
Definition: gnunet_nt_lib.h:50
uint32_t options
Optional options and flags for this address.
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
uint32_t num_bytes_pending
Number of bytes pending transmission for this session.
static int udp
Option -u: UDP requested.
Definition: gnunet-vpn.c:76
int enable_broadcasting
Is broadcasting enabled: GNUNET_YES or GNUNET_NO.
GNUNET_TRANSPORT_AddressStringCallback asc
Function to call with the result.
int GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
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.
size_t payload_size
Payload size of original unfragmented message.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
GNUNET_TRANSPORT_AddressToString address_to_string
Function that will be called to convert a binary address to a string (numeric conversion only)...
struct UDP_MessageWrapper * ipv6_queue_head
Head of messages in IPv6 queue.
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_allocate(const struct GNUNET_PeerIdentity *peer, const char *transport_name, const void *address, size_t address_length, enum GNUNET_HELLO_AddressInfo local_info)
Allocate an address struct.
Definition: address.c:73
unsigned int rc
Reference counter to indicate that this session is currently being used and must not be destroyed; se...
struct UDP_FragmentationContext * prev
Previous in linked list.
void GNUNET_BANDWIDTH_tracker_init(struct GNUNET_BANDWIDTH_Tracker *av, GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb, void *update_cb_cls, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit, uint32_t max_carry_s)
Initialize bandwidth tracker.
Definition: bandwidth.c:302
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.
uint64_t rel_value_us
The actual value.
const void * address
Binary representation of the address (plugin-specific).
struct GNUNET_ATS_Session * session
Session this message belongs to.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
static void enqueue(struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
Enqueue a message for transmission and update statistics.
struct PrettyPrinterContext * ppc_dll_tail
Running pretty printers: tail.
uint16_t aport
Port we advertise on.
Implementation of the UDP transport protocol.
common internal definitions for transport service
unsigned int msgs_in_queue
Number of messages waiting for transmission to this peer.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
void stop_broadcast(struct Plugin *plugin)
Stop broadcasting subsystem.
struct GNUNET_SCHEDULER_Task * timeout_task
Session timeout task.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
struct GNUNET_TIME_Relative flow_delay_for_other_peer
Desired delay for next sending we send to other peer.
The reading socket is ready.
Context information passed to each scheduler task.
static void free_session(struct GNUNET_ATS_Session *s)
Function to free last resources associated with a session.
struct Plugin * plugin
Pointer to the global plugin struct.
struct GNUNET_TIME_Absolute timeout
Message timeout.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
struct IPv4UdpAddress v4
IPv4 case.
GNUNET_TRANSPORT_DisconnectPeerFunction disconnect_peer
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
static void udp_plugin_select_v6(void *cls)
We have been notified that our readset has something to read.
const union UdpAddress * udp_addr
Address to find.
struct Plugin * plugin
The plugin.
char * bind6_address
Address we were told to bind to exclusively (IPv6).
int enable_ipv4
Is IPv4 enabled: GNUNET_YES or GNUNET_NO.
int is_inbound
GNUNET_YES if this is an inbound connection, GNUNET_NO if this is an outbound connection, GNUNET_SYSERR if connections of this plugin are so fundamentally bidirectional that they have no &#39;initiator&#39;
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:245
struct GNUNET_DEFRAGMENT_Context * GNUNET_DEFRAGMENT_context_create(struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, unsigned int num_msgs, void *cls, GNUNET_FRAGMENT_MessageProcessor proc, GNUNET_DEFRAGMENT_AckProcessor ackp)
Create a defragmentation context.
static struct GNUNET_ATS_Session * udp_plugin_lookup_session(void *cls, const struct GNUNET_HELLO_Address *address)
Locate an existing session the transport service is using to send data to another peer...
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
enum GNUNET_TRANSPORT_SessionState state
New state of the session.
struct GNUNET_MessageHeader header
Message header.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_RESOLVER_RequestHandle * resolver_handle
Resolver handle.
uint16_t u4_port
Port number, in network byte order.
UDP Message-Packet header (after defragmentation).
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Absolute transmission_time
Desired transmission time for this message, based on the flow limiting information we got from the ot...
#define STRERROR(i)
Definition: plibc.h:676
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:417
GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
GNUNET_TRANSPORT_SessionMonitorSetup setup_monitor
Function to monitor the sessions managed by the plugin.
uint32_t reserved
Always zero for now.
int GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:522
Closure for append_port().
static void qc_message_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We are finished with a message from the message queue.
uint16_t port
Port to add after the IP address.
struct in6_addr ipv6_addr
IPv6 address.
struct GNUNET_FRAGMENT_Context * GNUNET_FRAGMENT_context_create(struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, struct GNUNET_BANDWIDTH_Tracker *tracker, struct GNUNET_TIME_Relative msg_delay, struct GNUNET_TIME_Relative ack_delay, const struct GNUNET_MessageHeader *msg, GNUNET_FRAGMENT_MessageProcessor proc, void *proc_cls)
Create a fragmentation context for the given message.
#define GNUNET_CONSTANTS_LATENCY_WARN
After what amount of latency for a message do we print a warning?
static void read_process_ack(struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, const union UdpAddress *udp_addr, socklen_t udp_addr_len)
Handle a GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK message.
struct GNUNET_TIME_Absolute timeout
When does this session time out.
static struct Experiment * e
static void enqueue_fragment(void *cls, const struct GNUNET_MessageHeader *msg)
Function that is called with messages created by the fragmentation module.
static void fragmented_message_done(struct UDP_FragmentationContext *frag_ctx, int result)
We have completed our (attempt) to transmit a message that had to be fragmented – either because we ...
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
Wide area network (i.e.
Definition: gnunet_nt_lib.h:55
#define GNUNET_NO
Definition: gnunet_common.h:81
static int numeric
Option -n.
static int udp_plugin_check_address(void *cls, const void *addr, size_t addrlen)
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static void ack_message_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We finished sending an acknowledgement.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
const struct GNUNET_NETWORK_FDSet * read_ready
Set of file descriptors ready for reading; note that additional bits may be set that were not in the ...
struct GNUNET_TIME_Relative flow_delay_from_other_peer
Desired delay for transmissions we received from other peer.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:393
int64_t bytes_in_buffer
Bytes currently in buffer.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void udp_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...
struct GNUNET_HELLO_Address * address
Address.
static int process_inbound_tokenized_messages(void *cls, const struct GNUNET_MessageHeader *hdr)
Message tokenizer has broken up an incomming message.
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
int enable_broadcasting_receiving
Is receiving broadcasts enabled: GNUNET_YES or GNUNET_NO.
struct GNUNET_TIME_Relative last_expected_ack_delay
expected delay for ACKs
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
struct GNUNET_NETWORK_Handle * sockv4
The read socket for IPv4.
static ssize_t udp_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...
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_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_get(const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls)
Perform a reverse DNS lookup.
void * asc_cls
Clsoure for asc.
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 void udp_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
Disconnect from a remote node.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define UDP_MTU
MTU for fragmentation subsystem.
uint16_t u6_port
Port number, in network byte order.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
uint64_t abs_value_us
The actual value.
enum GNUNET_SCHEDULER_Reason reason
Reason why the task is run now.
struct UDP_FragmentationContext * frag_ctx
Fragmentation context.
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:35
const char * GNUNET_FRAGMENT_print_ack(const struct GNUNET_MessageHeader *ack)
Convert an ACK message to a printable format suitable for logging.
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...
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
#define UDP_SESSION_TIME_OUT
After how much inactivity should a UDP session time out?
void GNUNET_FRAGMENT_context_transmission_done(struct GNUNET_FRAGMENT_Context *fc)
Continuation to call from the &#39;proc&#39; function after the fragment has been transmitted (and hence the ...
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
int GNUNET_NAT_test_address(struct GNUNET_NAT_Handle *nh, const void *addr, socklen_t addrlen)
Test if the given address is (currently) a plausible IP address for this peer.
Definition: nat_api.c:623
const union UdpAddress * udp_addr
Source address this receive context is for (allocated at the end of the struct).
static void append_port(void *cls, const char *hostname)
Append our port and forward the result.
GNUNET_TRANSPORT_PluginReceiveCallback receive
Function that should be called by the transport plugin whenever a message is received.
GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout
Function that will be called whenever the transport service wants to notify the plugin that a session...
static struct GNUNET_ATS_SolverFunctions * plugin
Our solver.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
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
Fragmentation context.
Definition: fragmentation.c:40
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
struct UDP_MessageWrapper * next
DLL of messages, next element.
enum GNUNET_NetworkType network_type
Network type the address belongs to.
Context to send fragmented messages.
struct GNUNET_SCHEDULER_Task * select_task_v4
ID of select task for IPv4.
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.
#define GNUNET_memcpy(dst, src, n)
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
struct GNUNET_TIME_Relative flow_delay_from_other_peer
Desired delay for transmissions we received from other peer.
static struct GNUNET_TIME_Relative interval
Definition: speedup.c:33
void GNUNET_DEFRAGMENT_context_destroy(struct GNUNET_DEFRAGMENT_Context *dc)
Destroy the given defragmentation context.
size_t on_wire_size
Bytes used to send all fragments on wire including UDP overhead.
void * libgnunet_plugin_transport_udp_done(void *cls)
The exported method.
Network format for IPv4 addresses.
static char * value
Value of the record to add/remove.
void(* GNUNET_TRANSPORT_AddressStringCallback)(void *cls, const char *address, int res)
Function called by the pretty printer for the resolved address for each human-readable address obtain...
GNUNET_TRANSPORT_StringToAddress string_to_address
Function that will be called to convert a string address to binary (numeric conversion only)...
void setup_broadcast(struct Plugin *plugin, struct sockaddr_in6 *server_addrv6, struct sockaddr_in *server_addrv4)
Setup broadcasting subsystem.
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:413
Information about ongoing sessions of the transport client.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
int GNUNET_NAT_stun_handle_packet(struct GNUNET_NAT_Handle *nh, const struct sockaddr *sender_addr, size_t sender_addr_len, const void *data, size_t data_size)
Handle an incoming STUN message.
Definition: nat_api.c:581
#define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE
Normal UDP message type.
uint32_t ipv4_addr
IPv4 address, in network byte order.
static struct GNUNET_NETWORK_Handle * bind_v6()
Create an IPv6 listen socket bound to our port.
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
int have_sender
Has the sender field been initialized yet?
static struct GNUNET_SCHEDULER_Task * t4
Task for IPv4 socket.
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task.
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?
struct PrettyPrinterContext * prev
DLL.
GNUNET_TRANSPORT_GetNetworkType get_network
Function to obtain the network type for a session.
Handle to a message stream tokenizer.
Definition: mst.c:43
static void udp_plugin_setup_monitor(void *cls, GNUNET_TRANSPORT_SessionInfoCallback sic, void *sic_cls)
Begin monitoring sessions of a plugin.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:727
ssize_t GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc, const void *message, size_t length, const struct sockaddr *dest_addr, socklen_t dest_len)
Send data to a particular destination (always non-blocking).
Definition: network.c:968
struct GNUNET_DEFRAGMENT_Context * defrag
Defragmentation context.
#define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
We keep a defragmentation queue per sender address.
static char buf[2048]
static enum GNUNET_NetworkType udp_plugin_get_network_for_address(void *cls, const struct GNUNET_HELLO_Address *address)
Function obtain the network type for an address.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition: time.c:317
struct GNUNET_MessageHeader header
Message header.
Closure for session_cmp_it().
static void udp_nat_port_map_callback(void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
Our external IP address/port mapping has changed.
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:87
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 ...
static int result
Global testing status.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:439
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
size_t udp_addr_len
Length of udp_addr.
struct GNUNET_PeerIdentity sender
What is the identity of the sender.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
int GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:116
struct GNUNET_TIME_Absolute session_timeout
At what time will this session timeout (unless activity happens)?
int in_destroy
Is this session about to be destroyed (sometimes we cannot destroy a session immediately as below us ...
static GNUNET_NETWORK_STRUCT_END void notify_session_monitor(struct 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 session_cmp_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Find a session with a matching address.
GNUNET_TRANSPORT_TransmitContinuation cont
External continuation to call upon completion of the transmission, NULL if this queue entry is not fo...
static int udp_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 * cont_cls
Closure for cont.
Heap with the minimum cost at the root.
struct GNUNET_ATS_Session * session
The session this fragmentation context belongs to.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
Information we track for each message in the queue.
static int udp_disconnect_session(void *cls, struct GNUNET_ATS_Session *s)
Functions with this signature are called whenever we need to close a session due to a disconnect or f...
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
Closure for find_receive_context().
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
void udp_broadcast_receive(struct Plugin *plugin, const char *buf, ssize_t size, const union UdpAddress *udp_addr, size_t udp_addr_len, enum GNUNET_NetworkType network_type)
We received a broadcast message.
static void fragment_msg_proc(void *cls, const struct GNUNET_MessageHeader *msg)
Process a defragmented message.
static int res
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
int GNUNET_FRAGMENT_process_ack(struct GNUNET_FRAGMENT_Context *fc, const struct GNUNET_MessageHeader *msg)
Process an acknowledgement message we got from the other side (to control re-transmits).
static void analyze_send_error(struct Plugin *plugin, const struct sockaddr *sa, socklen_t slen, int error)
We failed to transmit a message via UDP.
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.
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer for inbound messages.
Defragmentation context (one per connection).
struct GNUNET_TIME_Relative broadcast_interval
Broadcast interval.
uint32_t options
Optional options and flags for this address.
static struct GNUNET_TIME_Absolute start_time
Start time of the current round; used to determine how long one iteration takes (which influences how...
struct DefragContext * rc
Where to store the result.
struct GNUNET_SCHEDULER_Task * select_task_v6
ID of select task for IPv6.
Node in the heap.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition: nat_api.c:690
static struct UDP_MessageWrapper * remove_timeout_messages_and_select(struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
Removes messages from the transmission queue that have timed out, and then selects a message that sho...
static void schedule_select_v6(struct Plugin *plugin)
(re)schedule IPv6-select tasks for this plugin.
Network format for IPv6 addresses.
struct IPv6UdpAddress v6
IPv6 case.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
uint64_t GNUNET_CONTAINER_HeapCostType
Cost by which elements in a heap can be ordered.
struct GNUNET_ATS_Session * session
Session associated with this context.
static enum GNUNET_NetworkType udp_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
Function obtain the network type for a session.
Handle to a request given to the resolver.
Definition: resolver_api.c:100
enum GNUNET_NetworkType scope
ATS network type.
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition: nat_api.c:378
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
Data structure to track defragmentation contexts based on the source of the UDP traffic.
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".
static struct GNUNET_ATS_Session * udp_plugin_create_session(void *cls, const struct GNUNET_HELLO_Address *address, enum GNUNET_NetworkType network_type)
Allocate a new session for the given endpoint address.
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 PrettyPrinterContext * next
DLL.
struct GNUNET_PeerIdentity peer
For which peer is this an address?
struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_init(uint32_t bytes_per_second)
Create a new bandwidth value.
Definition: bandwidth.c:39
static struct GNUNET_ATS_Session * udp_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 void dequeue(struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
Remove the given message from the transmission queue and update all applicable statistics.
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
uint32_t delay
Desired delay for flow control, in us (in NBO).
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
static int disconnect_and_free_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Destroy a session, plugin is being unloaded.
static void schedule_select_v4(struct Plugin *plugin)
(re)schedule IPv4-select tasks for this plugin.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK
UDP ACK.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
struct UDP_MessageWrapper * ipv4_queue_tail
Tail of messages in IPv4 queue.
size_t udp_addr_len
Number of bytes in udp_addr.
Allow multiple values with the same key.
static void process_udp_message(struct Plugin *plugin, const struct UDPMessage *msg, const union UdpAddress *udp_addr, size_t udp_addr_len, enum GNUNET_NetworkType network_type)
We&#39;ve received a UDP Message.
struct GNUNET_TIME_Absolute start_time
Message enqueue time.
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.
struct GNUNET_TIME_Absolute start_time
Start time.
This is just an update about the session, the state did not change.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
char * msg_buf
Message with msg_size bytes including UDP-specific overhead.
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 UDP_FragmentationContext * next
Next in linked list.
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).
No additional information.
static void session_timeout(void *cls)
Session was idle, so disconnect it.
int GNUNET_CONTAINER_multipeermap_contains_value(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Check if the map contains the given value under the given key.
static char * hostname
Our hostname; we give this to all the peers we start.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to &#39;struct&#39;s...
struct GNUNET_CONTAINER_HeapNode * hnode
Node in the defrag heap.
#define GNUNET_PACKED
gcc-ism to get packed structs.
static int find_receive_context(void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, GNUNET_CONTAINER_HeapCostType cost)
Scan the heap for a receive context with the given address.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:79
struct UDP_MessageWrapper * ipv6_queue_tail
Tail of messages in IPv6 queue.
static int heap_cleanup_iterator(void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, GNUNET_CONTAINER_HeapCostType cost)
Function called on each entry in the defragmentation heap to clean it up.
static void udp_plugin_select_v4(void *cls)
We have been notified that our readset has something to read.
Handle for a plugin.
Definition: block.c:37
uint32_t options
Address options.
void * cont_cls
Closure for cont.
void * qc_cls
Closure for qc.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:373
struct GNUNET_PeerIdentity target
To whom are we talking to.
#define PLUGIN_NAME
static void udp_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.
Either an IPv4 or IPv6 UDP address.
static struct GNUNET_NETWORK_Handle * bind_v4()
Create an IPv4 listen socket bound to our port.
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
const char * udp_address_to_string(void *cls, const void *addr, size_t addrlen)
Function called for a quick conversion of the binary address to a numeric address.
static int inet_pton(int af, const char *cp, struct in_addr *buf)
Convert IPv4 address from text to binary form.
#define GNUNET_log(kind,...)
The session was created (first call for each session object).
Entry in list of pending tasks.
Definition: scheduler.c:134
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
struct GNUNET_ATS_Session * sessions
List of open sessions (or peer map, or...)
struct GNUNET_NETWORK_Handle * sockv6
The read socket for IPv6.
uint16_t port
Port used.
handle to a socket
Definition: network.c:46
char * bind4_address
Address we were told to bind to exclusively (IPv4).
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
void * cls
Closure to use for callbacks.
static unsigned int udp_query_keepalive_factor(void *cls)
Function that is called to get the keepalive factor.
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.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:525
struct GNUNET_CONTAINER_Heap * defrag_ctxs
Heap with all of our defragmentation activities.
int GNUNET_DEFRAGMENT_process_fragment(struct GNUNET_DEFRAGMENT_Context *dc, const struct GNUNET_MessageHeader *msg)
We have received a fragment.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
const struct GNUNET_HELLO_Address * address
Address we are looking for.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1478
UDP ACK Message-Packet header.
struct GNUNET_TIME_Relative last_expected_msg_delay
desired delay between UDP messages
QueueContinuation qc
Function to call once the message wrapper is being removed from the queue (with success or failure)...
struct GNUNET_ATS_Session * res
Set to session matching the address.
struct UDP_MessageWrapper * prev
DLL of messages, previous element.
struct PrettyPrinterContext * ppc_dll_head
Running pretty printers: head.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
struct GNUNET_BANDWIDTH_Tracker tracker
Bandwidth tracker to limit global UDP traffic.
#define GNUNET_MESSAGE_TYPE_FRAGMENT
FRAGMENT of a larger message.
uint32_t myoptions
Address options.
static void udp_select_send(struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
It is time to try to transmit a UDP message.
static void qc_fragment_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We are finished with a fragment in the message queue.
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:792
struct UDP_MessageWrapper * ipv4_queue_head
Head of messages in IPv4 queue.
static void udp_select_read(struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
Read and process a message from the given socket.
void GNUNET_CONTAINER_heap_iterate(const struct GNUNET_CONTAINER_Heap *heap, GNUNET_CONTAINER_HeapIterator iterator, void *iterator_cls)
Iterate over all entries in the heap.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON
Message send by a peer to notify the other to keep the session alive.
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.
GNUNET_TRANSPORT_TransmitContinuation cont
Function to call upon completion of the transmission.
struct UDP_FragmentationContext * frag_ctx
Context for dealing with fragments.
int GNUNET_NETWORK_fdset_isset(const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc)
Check whether a socket is part of the fd set.
Definition: network.c:1181
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.
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".
ssize_t GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length, struct sockaddr *src_addr, socklen_t *addrlen)
Read data from a socket (always non-blocking).
Definition: network.c:856
void GNUNET_FRAGMENT_context_destroy(struct GNUNET_FRAGMENT_Context *fc, struct GNUNET_TIME_Relative *msg_delay, struct GNUNET_TIME_Relative *ack_delay)
Destroy the given fragmentation context (stop calling &#39;proc&#39;, free resources).
struct Plugin * plugin
Reference to master plugin struct.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
static void read_process_fragment(struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, const union UdpAddress *udp_addr, size_t udp_addr_len, enum GNUNET_NetworkType network_type)
We received a fragment, process it.
static char * address
GNS address for this phone.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define UDP_MAX_MESSAGES_IN_DEFRAG
Number of messages we can defragment in parallel.
static unsigned int setup_sockets(struct Plugin *plugin, const struct sockaddr_in6 *bind_v6, const struct sockaddr_in *bind_v4)
Setup the UDP sockets (for IPv4 and IPv6) for the plugin.
#define LOG(kind,...)
void(* QueueContinuation)(void *cls, struct UDP_MessageWrapper *udpw, int result)
Function called when a message is removed from the transmission queue.
struct GNUNET_FRAGMENT_Context * frag
Handle for fragmentation.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:604
#define GNUNET_HELLO_address_free(addr)
Free an address.
size_t msg_size
Size of UDP message to send, including UDP-specific overhead.
void * libgnunet_plugin_transport_udp_init(void *cls)
The exported method.
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_STRINGS_to_address_ip(const char *addr, uint16_t addrlen, struct sockaddr_storage *r_buf)
Tries to convert addr string to an IP (v4 or v6) address.
Definition: strings.c:1409
void * sic_cls
Closure for sic.
#define GNUNET_malloc(size)
Wrapper around malloc.
int enable_ipv6
Is IPv6 enabled: GNUNET_YES or GNUNET_NO.
static struct GNUNET_FS_DownloadContext * dc
struct GNUNET_PeerIdentity sender
Who&#39;s message(s) are we defragmenting here? Only initialized once we succeeded and have_sender is set...
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
struct GNUNET_TIME_Absolute timeout
Message timeout.
static struct GNUNET_SCHEDULER_Task * t6
Task for IPv6 socket.
static int check_port(const struct Plugin *plugin, uint16_t in_port)
Check if the given port is plausible (must be either our listen port or our advertised port)...
GNUNET_TRANSPORT_GetNetworkTypeForAddress get_network_for_address
Function to obtain the network type for an address.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:1037
Category of last resort.
Definition: gnunet_nt_lib.h:40
struct GNUNET_TIME_Absolute next_frag_time
Transmission time for the next fragment.
static void reschedule_session_timeout(struct GNUNET_ATS_Session *s)
Increment session timeout due to activity.
static int ipv6
Option -6: IPv6 requested.
Definition: gnunet-vpn.c:66
struct GNUNET_PeerIdentity sender
What is the identity of the sender.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
High-quality operations are desired.