GNUnet  0.20.0
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 \
49  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
50 
59 #define UDP_MAX_MESSAGES_IN_DEFRAG 3
60 
68 #define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128
69 
70 
74 struct UDPMessage
75 {
80 
84  uint32_t reserved;
85 
90 };
91 
92 
97 {
101  struct PrettyPrinterContext *next;
102 
106  struct PrettyPrinterContext *prev;
107 
111  struct Plugin *plugin;
112 
117 
122 
126  void *asc_cls;
127 
132 
136  int ipv6;
137 
141  uint32_t options;
142 
146  uint16_t port;
147 };
148 
149 
153 struct GNUNET_ATS_Session
154 {
159 
164 
168  struct Plugin *plugin;
169 
174 
179 
186 
191 
196 
201 
206 
211 
216 
220  unsigned long long bytes_in_queue;
221 
225  unsigned int msgs_in_queue;
226 
233  unsigned int rc;
234 
239 
247 };
248 
249 
255 {
260 
264  struct Plugin *plugin;
265 
270 
275  const union UdpAddress *udp_addr;
276 
283 
287  size_t udp_addr_len;
288 
293 
298 };
299 
300 
305 {
310 
315 
319  struct Plugin *plugin;
320 
325 
330 
335 
339  void *cont_cls;
340 
345 
352 
359 
364 
368  size_t payload_size;
369 
373  size_t on_wire_size;
374 };
375 
376 
387 typedef void (*QueueContinuation) (void *cls,
388  struct UDP_MessageWrapper *udpw,
389  int result);
390 
391 
396 {
401 
406 
411 
415  char *msg_buf;
416 
422 
426  void *qc_cls;
427 
434 
438  void *cont_cls;
439 
446 
451 
457 
462 
466  size_t msg_size;
467 
471  size_t payload_size;
472 };
473 
474 
476 
481 {
486 
493 
498 };
499 
501 
502 
503 /* ************************* Monitoring *********** */
504 
505 
514 static void
516  struct GNUNET_ATS_Session *session,
518 {
520 
521  if (NULL == plugin->sic)
522  return;
523  if (GNUNET_YES == session->in_destroy)
524  return; /* already destroyed, just RC>0 left-over actions */
525  memset (&info, 0, sizeof(info));
526  info.state = state;
527  info.is_inbound = GNUNET_SYSERR; /* hard to say */
528  info.num_msg_pending = session->msgs_in_queue;
529  info.num_bytes_pending = session->bytes_in_queue;
530  /* info.receive_delay remains zero as this is not supported by UDP
531  (cannot selectively not receive from 'some' peer while continuing
532  to receive from others) */
533  info.session_timeout = session->timeout;
534  info.address = session->address;
535  plugin->sic (plugin->sic_cls, session, &info);
536 }
537 
538 
547 static int
549  const struct GNUNET_PeerIdentity *peer,
550  void *value)
551 {
552  struct Plugin *plugin = cls;
553  struct GNUNET_ATS_Session *session = value;
554 
557  return GNUNET_OK;
558 }
559 
560 
573 static void
576  void *sic_cls)
577 {
578  struct Plugin *plugin = cls;
579 
580  plugin->sic = sic;
581  plugin->sic_cls = sic_cls;
582  if (NULL != sic)
583  {
586  plugin);
587  /* signal end of first iteration */
588  sic (sic_cls, NULL, NULL);
589  }
590 }
591 
592 
593 /* ****************** Little Helpers ****************** */
594 
595 
601 static void
603 {
604  if (NULL != s->address)
605  {
607  s->address = NULL;
608  }
609  if (NULL != s->frag_ctx)
610  {
612  GNUNET_free (s->frag_ctx);
613  s->frag_ctx = NULL;
614  }
615  if (NULL != s->mst)
616  {
617  GNUNET_MST_destroy (s->mst);
618  s->mst = NULL;
619  }
620  GNUNET_free (s);
621 }
622 
623 
632 static unsigned int
634 {
635  return 15;
636 }
637 
638 
646 static enum GNUNET_NetworkType
647 udp_plugin_get_network (void *cls, struct GNUNET_ATS_Session *session)
648 {
649  return session->scope;
650 }
651 
652 
660 static enum GNUNET_NetworkType
662  const struct GNUNET_HELLO_Address *address)
663 {
664  struct Plugin *plugin = cls;
665  size_t addrlen;
666  struct sockaddr_in a4;
667  struct sockaddr_in6 a6;
668  const struct IPv4UdpAddress *u4;
669  const struct IPv6UdpAddress *u6;
670  const void *sb;
671  size_t sbs;
672 
673  addrlen = address->address_length;
674  if (addrlen == sizeof(struct IPv6UdpAddress))
675  {
676  GNUNET_assert (NULL != address->address); /* make static analysis happy */
677  u6 = address->address;
678  memset (&a6, 0, sizeof(a6));
679 #if HAVE_SOCKADDR_IN_SIN_LEN
680  a6.sin6_len = sizeof(a6);
681 #endif
682  a6.sin6_family = AF_INET6;
683  a6.sin6_port = u6->u6_port;
684  GNUNET_memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof(struct in6_addr));
685  sb = &a6;
686  sbs = sizeof(a6);
687  }
688  else if (addrlen == sizeof(struct IPv4UdpAddress))
689  {
690  GNUNET_assert (NULL != address->address); /* make static analysis happy */
691  u4 = address->address;
692  memset (&a4, 0, sizeof(a4));
693 #if HAVE_SOCKADDR_IN_SIN_LEN
694  a4.sin_len = sizeof(a4);
695 #endif
696  a4.sin_family = AF_INET;
697  a4.sin_port = u4->u4_port;
698  a4.sin_addr.s_addr = u4->ipv4_addr;
699  sb = &a4;
700  sbs = sizeof(a4);
701  }
702  else
703  {
704  GNUNET_break (0);
705  return GNUNET_NT_UNSPECIFIED;
706  }
707  return plugin->env->get_address_type (plugin->env->cls, sb, sbs);
708 }
709 
710 
711 /* ******************* Event loop ******************** */
712 
720 static void
721 udp_plugin_select_v4 (void *cls);
722 
723 
731 static void
732 udp_plugin_select_v6 (void *cls);
733 
734 
740 static void
742 {
743  struct GNUNET_TIME_Relative min_delay;
745  struct UDP_MessageWrapper *udpw;
746  struct UDP_MessageWrapper *min_udpw;
747 
748  if ((GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4))
749  {
750  /* Find a message ready to send:
751  * Flow delay from other peer is expired or not set (0) */
752  min_delay = GNUNET_TIME_UNIT_FOREVER_REL;
753  min_udpw = NULL;
754  for (udpw = plugin->ipv4_queue_head; NULL != udpw; udpw = udpw->next)
755  {
757  if (delay.rel_value_us < min_delay.rel_value_us)
758  {
759  min_delay = delay;
760  min_udpw = udpw;
761  }
762  }
763  if (NULL != plugin->select_task_v4)
764  GNUNET_SCHEDULER_cancel (plugin->select_task_v4);
765  if (NULL != min_udpw)
766  {
767  if (min_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
768  {
770  "Calculated flow delay for UDPv4 at %s for %s\n",
772  GNUNET_YES),
773  GNUNET_i2s (&min_udpw->session->target));
774  }
775  else
776  {
778  "Calculated flow delay for UDPv4 at %s for %s\n",
780  GNUNET_YES),
781  GNUNET_i2s (&min_udpw->session->target));
782  }
783  }
784  plugin->select_task_v4 =
786  plugin->sockv4,
788  plugin);
789  }
790 }
791 
792 
798 static void
800 {
801  struct GNUNET_TIME_Relative min_delay;
803  struct UDP_MessageWrapper *udpw;
804  struct UDP_MessageWrapper *min_udpw;
805 
806  if ((GNUNET_YES == plugin->enable_ipv6) && (NULL != plugin->sockv6))
807  {
808  min_delay = GNUNET_TIME_UNIT_FOREVER_REL;
809  min_udpw = NULL;
810  for (udpw = plugin->ipv6_queue_head; NULL != udpw; udpw = udpw->next)
811  {
813  if (delay.rel_value_us < min_delay.rel_value_us)
814  {
815  min_delay = delay;
816  min_udpw = udpw;
817  }
818  }
819  if (NULL != plugin->select_task_v6)
820  GNUNET_SCHEDULER_cancel (plugin->select_task_v6);
821  if (NULL != min_udpw)
822  {
823  if (min_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
824  {
826  "Calculated flow delay for UDPv6 at %s for %s\n",
828  GNUNET_YES),
829  GNUNET_i2s (&min_udpw->session->target));
830  }
831  else
832  {
834  "Calculated flow delay for UDPv6 at %s for %s\n",
836  GNUNET_YES),
837  GNUNET_i2s (&min_udpw->session->target));
838  }
839  }
840  plugin->select_task_v6 =
842  plugin->sockv6,
844  plugin);
845  }
846 }
847 
848 
849 /* ******************* Address to string and back ***************** */
850 
851 
863 const char *
864 udp_address_to_string (void *cls, const void *addr, size_t addrlen)
865 {
866  static char rbuf[INET6_ADDRSTRLEN + 10];
867  char buf[INET6_ADDRSTRLEN];
868  const void *sb;
869  struct in_addr a4;
870  struct in6_addr a6;
871  const struct IPv4UdpAddress *t4;
872  const struct IPv6UdpAddress *t6;
873  int af;
874  uint16_t port;
875  uint32_t options;
876 
877  if (NULL == addr)
878  {
879  GNUNET_break_op (0);
880  return NULL;
881  }
882 
883  if (addrlen == sizeof(struct IPv6UdpAddress))
884  {
885  t6 = addr;
886  af = AF_INET6;
887  options = ntohl (t6->options);
888  port = ntohs (t6->u6_port);
889  a6 = t6->ipv6_addr;
890  sb = &a6;
891  }
892  else if (addrlen == sizeof(struct IPv4UdpAddress))
893  {
894  t4 = addr;
895  af = AF_INET;
896  options = ntohl (t4->options);
897  port = ntohs (t4->u4_port);
898  a4.s_addr = t4->ipv4_addr;
899  sb = &a4;
900  }
901  else
902  {
903  GNUNET_break_op (0);
904  return NULL;
905  }
906  inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
907  GNUNET_snprintf (rbuf,
908  sizeof(rbuf),
909  (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u",
910  PLUGIN_NAME,
911  options,
912  buf,
913  port);
914  return rbuf;
915 }
916 
917 
929 static int
931  const char *addr,
932  uint16_t addrlen,
933  void **buf,
934  size_t *added)
935 {
936  struct sockaddr_storage socket_address;
937  char *address;
938  char *plugin;
939  char *optionstr;
940  uint32_t options;
941 
942  /* Format tcp.options.address:port */
943  address = NULL;
944  plugin = NULL;
945  optionstr = NULL;
946 
947  if ((NULL == addr) || (0 == addrlen))
948  {
949  GNUNET_break (0);
950  return GNUNET_SYSERR;
951  }
952  if ('\0' != addr[addrlen - 1])
953  {
954  GNUNET_break (0);
955  return GNUNET_SYSERR;
956  }
957  if (strlen (addr) != addrlen - 1)
958  {
959  GNUNET_break (0);
960  return GNUNET_SYSERR;
961  }
962  plugin = GNUNET_strdup (addr);
963  optionstr = strchr (plugin, '.');
964  if (NULL == optionstr)
965  {
966  GNUNET_break (0);
968  return GNUNET_SYSERR;
969  }
970  optionstr[0] = '\0';
971  optionstr++;
972  options = atol (optionstr);
973  address = strchr (optionstr, '.');
974  if (NULL == address)
975  {
976  GNUNET_break (0);
978  return GNUNET_SYSERR;
979  }
980  address[0] = '\0';
981  address++;
982 
983  if (GNUNET_OK !=
984  GNUNET_STRINGS_to_address_ip (address, strlen (address), &socket_address))
985  {
986  GNUNET_break (0);
988  return GNUNET_SYSERR;
989  }
991 
992  switch (socket_address.ss_family)
993  {
994  case AF_INET: {
995  struct IPv4UdpAddress *u4;
996  const struct sockaddr_in *in4 =
997  (const struct sockaddr_in *) &socket_address;
998 
999  u4 = GNUNET_new (struct IPv4UdpAddress);
1000  u4->options = htonl (options);
1001  u4->ipv4_addr = in4->sin_addr.s_addr;
1002  u4->u4_port = in4->sin_port;
1003  *buf = u4;
1004  *added = sizeof(struct IPv4UdpAddress);
1005  return GNUNET_OK;
1006  }
1007 
1008  case AF_INET6: {
1009  struct IPv6UdpAddress *u6;
1010  const struct sockaddr_in6 *in6 =
1011  (const struct sockaddr_in6 *) &socket_address;
1012 
1013  u6 = GNUNET_new (struct IPv6UdpAddress);
1014  u6->options = htonl (options);
1015  u6->ipv6_addr = in6->sin6_addr;
1016  u6->u6_port = in6->sin6_port;
1017  *buf = u6;
1018  *added = sizeof(struct IPv6UdpAddress);
1019  return GNUNET_OK;
1020  }
1021 
1022  default:
1023  GNUNET_break (0);
1024  return GNUNET_SYSERR;
1025  }
1026 }
1027 
1028 
1035 static void
1036 append_port (void *cls, const char *hostname)
1037 {
1038  struct PrettyPrinterContext *ppc = cls;
1039  struct Plugin *plugin = ppc->plugin;
1040  char *ret;
1041 
1042  if (NULL == hostname)
1043  {
1044  /* Final call, done */
1045  GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
1046  plugin->ppc_dll_tail,
1047  ppc);
1048  ppc->resolver_handle = NULL;
1049  ppc->asc (ppc->asc_cls, NULL, GNUNET_OK);
1050  GNUNET_free (ppc);
1051  return;
1052  }
1053  if (GNUNET_YES == ppc->ipv6)
1054  GNUNET_asprintf (&ret,
1055  "%s.%u.[%s]:%d",
1056  PLUGIN_NAME,
1057  ppc->options,
1058  hostname,
1059  ppc->port);
1060  else
1061  GNUNET_asprintf (&ret,
1062  "%s.%u.%s:%d",
1063  PLUGIN_NAME,
1064  ppc->options,
1065  hostname,
1066  ppc->port);
1067  ppc->asc (ppc->asc_cls, ret, GNUNET_OK);
1068  GNUNET_free (ret);
1069 }
1070 
1071 
1086 static void
1088  const char *type,
1089  const void *addr,
1090  size_t addrlen,
1091  int numeric,
1094  void *asc_cls)
1095 {
1096  struct Plugin *plugin = cls;
1097  struct PrettyPrinterContext *ppc;
1098  const struct sockaddr *sb;
1099  size_t sbs;
1100  struct sockaddr_in a4;
1101  struct sockaddr_in6 a6;
1102  const struct IPv4UdpAddress *u4;
1103  const struct IPv6UdpAddress *u6;
1104  uint16_t port;
1105  uint32_t options;
1106 
1107  if (addrlen == sizeof(struct IPv6UdpAddress))
1108  {
1109  u6 = addr;
1110  memset (&a6, 0, sizeof(a6));
1111  a6.sin6_family = AF_INET6;
1112 #if HAVE_SOCKADDR_IN_SIN_LEN
1113  a6.sin6_len = sizeof(a6);
1114 #endif
1115  a6.sin6_port = u6->u6_port;
1116  a6.sin6_addr = u6->ipv6_addr;
1117  port = ntohs (u6->u6_port);
1118  options = ntohl (u6->options);
1119  sb = (const struct sockaddr *) &a6;
1120  sbs = sizeof(a6);
1121  }
1122  else if (addrlen == sizeof(struct IPv4UdpAddress))
1123  {
1124  u4 = addr;
1125  memset (&a4, 0, sizeof(a4));
1126  a4.sin_family = AF_INET;
1127 #if HAVE_SOCKADDR_IN_SIN_LEN
1128  a4.sin_len = sizeof(a4);
1129 #endif
1130  a4.sin_port = u4->u4_port;
1131  a4.sin_addr.s_addr = u4->ipv4_addr;
1132  port = ntohs (u4->u4_port);
1133  options = ntohl (u4->options);
1134  sb = (const struct sockaddr *) &a4;
1135  sbs = sizeof(a4);
1136  }
1137  else
1138  {
1139  /* invalid address */
1140  GNUNET_break_op (0);
1141  asc (asc_cls, NULL, GNUNET_SYSERR);
1142  asc (asc_cls, NULL, GNUNET_OK);
1143  return;
1144  }
1145  ppc = GNUNET_new (struct PrettyPrinterContext);
1146  ppc->plugin = plugin;
1147  ppc->asc = asc;
1148  ppc->asc_cls = asc_cls;
1149  ppc->port = port;
1150  ppc->options = options;
1151  if (addrlen == sizeof(struct IPv6UdpAddress))
1152  ppc->ipv6 = GNUNET_YES;
1153  else
1154  ppc->ipv6 = GNUNET_NO;
1155  GNUNET_CONTAINER_DLL_insert (plugin->ppc_dll_head, plugin->ppc_dll_tail, ppc);
1157  sbs,
1158  ! numeric,
1159  timeout,
1160  &append_port,
1161  ppc);
1162 }
1163 
1164 
1174 static int
1175 check_port (const struct Plugin *plugin, uint16_t in_port)
1176 {
1177  if ((plugin->port == in_port) || (plugin->aport == in_port))
1178  return GNUNET_OK;
1179  return GNUNET_SYSERR;
1180 }
1181 
1182 
1198 static int
1199 udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
1200 {
1201  struct Plugin *plugin = cls;
1202  const struct IPv4UdpAddress *v4;
1203  const struct IPv6UdpAddress *v6;
1204 
1205  if (sizeof(struct IPv4UdpAddress) == addrlen)
1206  {
1207  struct sockaddr_in s4;
1208 
1209  v4 = (const struct IPv4UdpAddress *) addr;
1210  if (GNUNET_OK != check_port (plugin, ntohs (v4->u4_port)))
1211  return GNUNET_SYSERR;
1212  memset (&s4, 0, sizeof(s4));
1213  s4.sin_family = AF_INET;
1214 #if HAVE_SOCKADDR_IN_SIN_LEN
1215  s4.sin_len = sizeof(s4);
1216 #endif
1217  s4.sin_port = v4->u4_port;
1218  s4.sin_addr.s_addr = v4->ipv4_addr;
1219 
1220  if (GNUNET_OK !=
1221  GNUNET_NAT_test_address (plugin->nat, &s4, sizeof(struct sockaddr_in)))
1222  return GNUNET_SYSERR;
1223  }
1224  else if (sizeof(struct IPv6UdpAddress) == addrlen)
1225  {
1226  struct sockaddr_in6 s6;
1227 
1228  v6 = (const struct IPv6UdpAddress *) addr;
1229  if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
1230  return GNUNET_OK; /* plausible, if unlikely... */
1231  memset (&s6, 0, sizeof(s6));
1232  s6.sin6_family = AF_INET6;
1233 #if HAVE_SOCKADDR_IN_SIN_LEN
1234  s6.sin6_len = sizeof(s6);
1235 #endif
1236  s6.sin6_port = v6->u6_port;
1237  s6.sin6_addr = v6->ipv6_addr;
1238 
1240  &s6,
1241  sizeof(struct sockaddr_in6)))
1242  return GNUNET_SYSERR;
1243  }
1244  else
1245  {
1246  GNUNET_break_op (0);
1247  return GNUNET_SYSERR;
1248  }
1249  return GNUNET_OK;
1250 }
1251 
1252 
1265 static void
1267  void **app_ctx,
1268  int add_remove,
1270  const struct sockaddr *addr,
1271  socklen_t addrlen)
1272 {
1273  struct Plugin *plugin = cls;
1274  struct GNUNET_HELLO_Address *address;
1275  struct IPv4UdpAddress u4;
1276  struct IPv6UdpAddress u6;
1277  void *arg;
1278  size_t args;
1279 
1280  (void) app_ctx;
1282  (GNUNET_YES == add_remove) ? "NAT notification to add address `%s'\n"
1283  : "NAT notification to remove address `%s'\n",
1284  GNUNET_a2s (addr, addrlen));
1285  /* convert 'address' to our internal format */
1286  switch (addr->sa_family)
1287  {
1288  case AF_INET: {
1289  const struct sockaddr_in *i4;
1290 
1291  GNUNET_assert (sizeof(struct sockaddr_in) == addrlen);
1292  i4 = (const struct sockaddr_in *) addr;
1293  if (0 == ntohs (i4->sin_port))
1294  return; /* Port = 0 means unmapped, ignore these for UDP. */
1295  memset (&u4, 0, sizeof(u4));
1296  u4.options = htonl (plugin->myoptions);
1297  u4.ipv4_addr = i4->sin_addr.s_addr;
1298  u4.u4_port = i4->sin_port;
1299  arg = &u4;
1300  args = sizeof(struct IPv4UdpAddress);
1301  break;
1302  }
1303 
1304  case AF_INET6: {
1305  const struct sockaddr_in6 *i6;
1306 
1307  GNUNET_assert (sizeof(struct sockaddr_in6) == addrlen);
1308  i6 = (const struct sockaddr_in6 *) addr;
1309  if (0 == ntohs (i6->sin6_port))
1310  return; /* Port = 0 means unmapped, ignore these for UDP. */
1311  memset (&u6, 0, sizeof(u6));
1312  u6.options = htonl (plugin->myoptions);
1313  u6.ipv6_addr = i6->sin6_addr;
1314  u6.u6_port = i6->sin6_port;
1315  arg = &u6;
1316  args = sizeof(struct IPv6UdpAddress);
1317  break;
1318  }
1319 
1320  default:
1321  GNUNET_break (0);
1322  return;
1323  }
1324  /* modify our published address list */
1325  /* TODO: use 'ac' here in the future... */
1326  address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1327  PLUGIN_NAME,
1328  arg,
1329  args,
1331  plugin->env->notify_address (plugin->env->cls, add_remove, address);
1333 }
1334 
1335 
1336 /* ********************* Finding sessions ******************* */
1337 
1338 
1343 {
1348 
1353 };
1354 
1355 
1364 static int
1365 session_cmp_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
1366 {
1367  struct GNUNET_ATS_SessionCompareContext *cctx = cls;
1368  struct GNUNET_ATS_Session *s = value;
1369 
1370  if (0 == GNUNET_HELLO_address_cmp (s->address, cctx->address))
1371  {
1373  cctx->res = s;
1374  return GNUNET_NO;
1375  }
1376  return GNUNET_OK;
1377 }
1378 
1379 
1389 static struct GNUNET_ATS_Session *
1391  const struct GNUNET_HELLO_Address *address)
1392 {
1393  struct Plugin *plugin = cls;
1394  const struct IPv6UdpAddress *udp_a6;
1395  const struct IPv4UdpAddress *udp_a4;
1397 
1398  if (NULL == address->address)
1399  {
1400  GNUNET_break (0);
1401  return NULL;
1402  }
1403  if (sizeof(struct IPv4UdpAddress) == address->address_length)
1404  {
1405  if (NULL == plugin->sockv4)
1406  return NULL;
1407  udp_a4 = (const struct IPv4UdpAddress *) address->address;
1408  if (0 == udp_a4->u4_port)
1409  {
1410  GNUNET_break (0);
1411  return NULL;
1412  }
1413  }
1414  else if (sizeof(struct IPv6UdpAddress) == address->address_length)
1415  {
1416  if (NULL == plugin->sockv6)
1417  return NULL;
1418  udp_a6 = (const struct IPv6UdpAddress *) address->address;
1419  if (0 == udp_a6->u6_port)
1420  {
1421  GNUNET_break (0);
1422  return NULL;
1423  }
1424  }
1425  else
1426  {
1427  GNUNET_break (0);
1428  return NULL;
1429  }
1430 
1431  /* check if session already exists */
1432  cctx.address = address;
1433  cctx.res = NULL;
1435  "Looking for existing session for peer `%s' with address `%s'\n",
1436  GNUNET_i2s (&address->peer),
1438  address->address,
1439  address->address_length));
1441  &address->peer,
1442  &session_cmp_it,
1443  &cctx);
1444  if (NULL == cctx.res)
1445  return NULL;
1446  LOG (GNUNET_ERROR_TYPE_DEBUG, "Found existing session %p\n", cctx.res);
1447  return cctx.res;
1448 }
1449 
1450 
1451 /* ********************** Timeout ****************** */
1452 
1453 
1459 static void
1461 {
1462  if (GNUNET_YES == s->in_destroy)
1463  return;
1464  GNUNET_assert (NULL != s->timeout_task);
1466 }
1467 
1468 
1478 static void
1480  const struct GNUNET_PeerIdentity *peer,
1481  struct GNUNET_ATS_Session *session)
1482 {
1483  struct Plugin *plugin = cls;
1484 
1485  if (GNUNET_YES !=
1487  peer,
1488  session))
1489  {
1490  GNUNET_break (0);
1491  return;
1492  }
1493  /* Reschedule session timeout */
1494  reschedule_session_timeout (session);
1495 }
1496 
1497 
1498 /* ************************* Sending ************************ */
1499 
1500 
1508 static void
1509 dequeue (struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
1510 {
1511  struct GNUNET_ATS_Session *session = udpw->session;
1512 
1513  if (plugin->bytes_in_buffer < udpw->msg_size)
1514  {
1515  GNUNET_break (0);
1516  }
1517  else
1518  {
1519  GNUNET_STATISTICS_update (plugin->env->stats,
1520  "# UDP, total bytes in send buffers",
1521  -(long long) udpw->msg_size,
1522  GNUNET_NO);
1523  plugin->bytes_in_buffer -= udpw->msg_size;
1524  }
1525  GNUNET_STATISTICS_update (plugin->env->stats,
1526  "# UDP, total messages in send buffers",
1527  -1,
1528  GNUNET_NO);
1529  if (sizeof(struct IPv4UdpAddress) == udpw->session->address->address_length)
1530  {
1531  GNUNET_CONTAINER_DLL_remove (plugin->ipv4_queue_head,
1532  plugin->ipv4_queue_tail,
1533  udpw);
1534  }
1535  else if (sizeof(struct IPv6UdpAddress) ==
1536  udpw->session->address->address_length)
1537  {
1538  GNUNET_CONTAINER_DLL_remove (plugin->ipv6_queue_head,
1539  plugin->ipv6_queue_tail,
1540  udpw);
1541  }
1542  else
1543  {
1544  GNUNET_break (0);
1545  return;
1546  }
1547  GNUNET_assert (session->msgs_in_queue > 0);
1548  session->msgs_in_queue--;
1549  GNUNET_assert (session->bytes_in_queue >= udpw->msg_size);
1550  session->bytes_in_queue -= udpw->msg_size;
1551 }
1552 
1553 
1560 static void
1561 enqueue (struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
1562 {
1563  struct GNUNET_ATS_Session *session = udpw->session;
1564 
1565  if (GNUNET_YES == session->in_destroy)
1566  {
1567  GNUNET_break (0);
1568  GNUNET_free (udpw);
1569  return;
1570  }
1571  if (plugin->bytes_in_buffer > INT64_MAX - udpw->msg_size)
1572  {
1573  GNUNET_break (0);
1574  }
1575  else
1576  {
1577  GNUNET_STATISTICS_update (plugin->env->stats,
1578  "# UDP, total bytes in send buffers",
1579  udpw->msg_size,
1580  GNUNET_NO);
1581  plugin->bytes_in_buffer += udpw->msg_size;
1582  }
1583  GNUNET_STATISTICS_update (plugin->env->stats,
1584  "# UDP, total messages in send buffers",
1585  1,
1586  GNUNET_NO);
1587  if (sizeof(struct IPv4UdpAddress) == udpw->session->address->address_length)
1588  {
1589  GNUNET_CONTAINER_DLL_insert (plugin->ipv4_queue_head,
1590  plugin->ipv4_queue_tail,
1591  udpw);
1592  }
1593  else if (sizeof(struct IPv6UdpAddress) ==
1594  udpw->session->address->address_length)
1595  {
1596  GNUNET_CONTAINER_DLL_insert (plugin->ipv6_queue_head,
1597  plugin->ipv6_queue_tail,
1598  udpw);
1599  }
1600  else
1601  {
1602  GNUNET_break (0);
1603  udpw->cont (udpw->cont_cls,
1604  &session->target,
1605  GNUNET_SYSERR,
1606  udpw->msg_size,
1607  0);
1608  GNUNET_free (udpw);
1609  return;
1610  }
1611  session->msgs_in_queue++;
1612  session->bytes_in_queue += udpw->msg_size;
1613 }
1614 
1615 
1626 static void
1628 {
1629  struct Plugin *plugin = frag_ctx->plugin;
1630  struct GNUNET_ATS_Session *s = frag_ctx->session;
1631  struct UDP_MessageWrapper *udpw;
1632  struct UDP_MessageWrapper *tmp;
1633  size_t overhead;
1634  struct GNUNET_TIME_Relative delay;
1635 
1637  "%p: Fragmented message removed with result %s\n",
1638  frag_ctx,
1639  (result == GNUNET_SYSERR) ? "FAIL" : "SUCCESS");
1640  /* Call continuation for fragmented message */
1641  if (frag_ctx->on_wire_size >= frag_ctx->payload_size)
1642  overhead = frag_ctx->on_wire_size - frag_ctx->payload_size;
1643  else
1644  overhead = frag_ctx->on_wire_size;
1647  {
1649  "Fragmented message acknowledged after %s (expected at %s)\n",
1652  }
1653  else
1654  {
1656  "Fragmented message acknowledged after %s (expected at %s)\n",
1659  }
1660 
1661  if (NULL != frag_ctx->cont)
1662  frag_ctx->cont (frag_ctx->cont_cls,
1663  &s->target,
1664  result,
1665  s->frag_ctx->payload_size,
1666  frag_ctx->on_wire_size);
1667  GNUNET_STATISTICS_update (plugin->env->stats,
1668  "# UDP, fragmented messages active",
1669  -1,
1670  GNUNET_NO);
1671 
1672  if (GNUNET_OK == result)
1673  {
1674  GNUNET_STATISTICS_update (plugin->env->stats,
1675  "# UDP, fragmented msgs, messages, sent, success",
1676  1,
1677  GNUNET_NO);
1678  GNUNET_STATISTICS_update (plugin->env->stats,
1679  "# UDP, fragmented msgs, bytes payload, sent, success",
1680  s->frag_ctx->payload_size,
1681  GNUNET_NO);
1683  plugin->env->stats,
1684  "# UDP, fragmented msgs, bytes overhead, sent, success",
1685  overhead,
1686  GNUNET_NO);
1687  GNUNET_STATISTICS_update (plugin->env->stats,
1688  "# UDP, total, bytes overhead, sent",
1689  overhead,
1690  GNUNET_NO);
1691  GNUNET_STATISTICS_update (plugin->env->stats,
1692  "# UDP, total, bytes payload, sent",
1693  s->frag_ctx->payload_size,
1694  GNUNET_NO);
1695  }
1696  else
1697  {
1698  GNUNET_STATISTICS_update (plugin->env->stats,
1699  "# UDP, fragmented msgs, messages, sent, failure",
1700  1,
1701  GNUNET_NO);
1702  GNUNET_STATISTICS_update (plugin->env->stats,
1703  "# UDP, fragmented msgs, bytes payload, sent, failure",
1704  s->frag_ctx->payload_size,
1705  GNUNET_NO);
1706  GNUNET_STATISTICS_update (plugin->env->stats,
1707  "# UDP, fragmented msgs, bytes payload, sent, failure",
1708  overhead,
1709  GNUNET_NO);
1710  GNUNET_STATISTICS_update (plugin->env->stats,
1711  "# UDP, fragmented msgs, bytes payload, sent, failure",
1712  overhead,
1713  GNUNET_NO);
1714  }
1715 
1716  /* Remove remaining fragments from queue, no need to transmit those
1717  any longer. */
1718  if (s->address->address_length == sizeof(struct IPv6UdpAddress))
1719  {
1720  udpw = plugin->ipv6_queue_head;
1721  while (NULL != udpw)
1722  {
1723  tmp = udpw->next;
1724  if ((udpw->frag_ctx != NULL) && (udpw->frag_ctx == frag_ctx))
1725  {
1726  dequeue (plugin, udpw);
1727  GNUNET_free (udpw);
1728  }
1729  udpw = tmp;
1730  }
1731  }
1732  if (s->address->address_length == sizeof(struct IPv4UdpAddress))
1733  {
1734  udpw = plugin->ipv4_queue_head;
1735  while (NULL != udpw)
1736  {
1737  tmp = udpw->next;
1738  if ((NULL != udpw->frag_ctx) && (udpw->frag_ctx == frag_ctx))
1739  {
1740  dequeue (plugin, udpw);
1741  GNUNET_free (udpw);
1742  }
1743  udpw = tmp;
1744  }
1745  }
1750  s->frag_ctx = NULL;
1751  GNUNET_free (frag_ctx);
1752 }
1753 
1754 
1763 static void
1764 qc_fragment_sent (void *cls, struct UDP_MessageWrapper *udpw, int result)
1765 {
1766  struct Plugin *plugin = cls;
1767 
1768  GNUNET_assert (NULL != udpw->frag_ctx);
1769  if (GNUNET_OK == result)
1770  {
1772  "Fragment of message with %u bytes transmitted to %s\n",
1773  (unsigned int) udpw->payload_size,
1774  GNUNET_i2s (&udpw->session->target));
1776  GNUNET_STATISTICS_update (plugin->env->stats,
1777  "# UDP, fragmented msgs, fragments, sent, success",
1778  1,
1779  GNUNET_NO);
1781  plugin->env->stats,
1782  "# UDP, fragmented msgs, fragments bytes, sent, success",
1783  udpw->msg_size,
1784  GNUNET_NO);
1785  }
1786  else
1787  {
1789  "Failed to transmit fragment of message with %u bytes to %s\n",
1790  (unsigned int) udpw->payload_size,
1791  GNUNET_i2s (&udpw->session->target));
1793  GNUNET_STATISTICS_update (plugin->env->stats,
1794  "# UDP, fragmented msgs, fragments, sent, failure",
1795  1,
1796  GNUNET_NO);
1798  plugin->env->stats,
1799  "# UDP, fragmented msgs, fragments bytes, sent, failure",
1800  udpw->msg_size,
1801  GNUNET_NO);
1802  }
1803 }
1804 
1805 
1815 static void
1816 enqueue_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
1817 {
1818  struct UDP_FragmentationContext *frag_ctx = cls;
1819  struct Plugin *plugin = frag_ctx->plugin;
1820  struct UDP_MessageWrapper *udpw;
1821  struct GNUNET_ATS_Session *session = frag_ctx->session;
1822  size_t msg_len = ntohs (msg->size);
1823 
1824  LOG (GNUNET_ERROR_TYPE_DEBUG, "Enqueuing fragment with %lu bytes\n",
1825  (unsigned long) msg_len);
1826  udpw = GNUNET_malloc (sizeof(struct UDP_MessageWrapper) + msg_len);
1827  udpw->session = session;
1828  udpw->msg_buf = (char *) &udpw[1];
1829  udpw->msg_size = msg_len;
1830  udpw->payload_size = msg_len; /* FIXME: minus fragment overhead */
1831  udpw->timeout = frag_ctx->timeout;
1832  udpw->start_time = frag_ctx->start_time;
1837  udpw->frag_ctx = frag_ctx;
1838  udpw->qc = &qc_fragment_sent;
1839  udpw->qc_cls = plugin;
1840  GNUNET_memcpy (udpw->msg_buf, msg, msg_len);
1841  enqueue (plugin, udpw);
1842  if (session->address->address_length == sizeof(struct IPv4UdpAddress))
1844  else
1846 }
1847 
1848 
1857 static void
1858 qc_message_sent (void *cls, struct UDP_MessageWrapper *udpw, int result)
1859 {
1860  struct Plugin *plugin = cls;
1861  size_t overhead;
1862  struct GNUNET_TIME_Relative delay;
1863 
1864  if (udpw->msg_size >= udpw->payload_size)
1865  overhead = udpw->msg_size - udpw->payload_size;
1866  else
1867  overhead = udpw->msg_size;
1868 
1869  if (NULL != udpw->cont)
1870  {
1873  {
1875  "Message sent via UDP with delay of %s\n",
1877  }
1878  else
1879  {
1881  "Message sent via UDP with delay of %s\n",
1883  }
1884  udpw->cont (udpw->cont_cls,
1885  &udpw->session->target,
1886  result,
1887  udpw->payload_size,
1888  overhead);
1889  }
1890  if (GNUNET_OK == result)
1891  {
1892  GNUNET_STATISTICS_update (plugin->env->stats,
1893  "# UDP, unfragmented msgs, messages, sent, success",
1894  1,
1895  GNUNET_NO);
1897  plugin->env->stats,
1898  "# UDP, unfragmented msgs, bytes payload, sent, success",
1899  udpw->payload_size,
1900  GNUNET_NO);
1902  plugin->env->stats,
1903  "# UDP, unfragmented msgs, bytes overhead, sent, success",
1904  overhead,
1905  GNUNET_NO);
1906  GNUNET_STATISTICS_update (plugin->env->stats,
1907  "# UDP, total, bytes overhead, sent",
1908  overhead,
1909  GNUNET_NO);
1910  GNUNET_STATISTICS_update (plugin->env->stats,
1911  "# UDP, total, bytes payload, sent",
1912  udpw->payload_size,
1913  GNUNET_NO);
1914  }
1915  else
1916  {
1917  GNUNET_STATISTICS_update (plugin->env->stats,
1918  "# UDP, unfragmented msgs, messages, sent, failure",
1919  1,
1920  GNUNET_NO);
1922  plugin->env->stats,
1923  "# UDP, unfragmented msgs, bytes payload, sent, failure",
1924  udpw->payload_size,
1925  GNUNET_NO);
1927  plugin->env->stats,
1928  "# UDP, unfragmented msgs, bytes overhead, sent, failure",
1929  overhead,
1930  GNUNET_NO);
1931  }
1932 }
1933 
1934 
1962 static ssize_t
1963 udp_plugin_send (void *cls,
1964  struct GNUNET_ATS_Session *s,
1965  const char *msgbuf,
1966  size_t msgbuf_size,
1967  unsigned int priority,
1968  struct GNUNET_TIME_Relative to,
1970  void *cont_cls)
1971 {
1972  struct Plugin *plugin = cls;
1973  size_t udpmlen = msgbuf_size + sizeof(struct UDPMessage);
1974  struct UDP_FragmentationContext *frag_ctx;
1975  struct UDP_MessageWrapper *udpw;
1976  struct UDPMessage *udp;
1977  char mbuf[udpmlen] GNUNET_ALIGN;
1978  struct GNUNET_TIME_Relative latency;
1979 
1980  if ((sizeof(struct IPv6UdpAddress) == s->address->address_length) &&
1981  (NULL == plugin->sockv6))
1982  return GNUNET_SYSERR;
1983  if ((sizeof(struct IPv4UdpAddress) == s->address->address_length) &&
1984  (NULL == plugin->sockv4))
1985  return GNUNET_SYSERR;
1986  if (udpmlen >= GNUNET_MAX_MESSAGE_SIZE)
1987  {
1988  GNUNET_break (0);
1989  return GNUNET_SYSERR;
1990  }
1991  if (GNUNET_YES !=
1993  &s->target,
1994  s))
1995  {
1996  GNUNET_break (0);
1997  return GNUNET_SYSERR;
1998  }
2000  "UDP transmits %lu-byte message to `%s' using address `%s'\n",
2001  (unsigned long) udpmlen,
2002  GNUNET_i2s (&s->target),
2004  s->address->address,
2005  s->address->address_length));
2006 
2007  udp = (struct UDPMessage *) mbuf;
2008  udp->header.size = htons (udpmlen);
2009  udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE);
2010  udp->reserved = htonl (0);
2011  udp->sender = *plugin->env->my_identity;
2012 
2013  /* We do not update the session time out here! Otherwise this
2014  * session will not timeout since we send keep alive before session
2015  * can timeout.
2016  *
2017  * For UDP we update session timeout only on receive, this will
2018  * cover keep alives, since remote peer will reply with keep alive
2019  * responses!
2020  */if (udpmlen <= UDP_MTU)
2021  {
2022  /* unfragmented message */
2023  udpw = GNUNET_malloc (sizeof(struct UDP_MessageWrapper) + udpmlen);
2024  udpw->session = s;
2025  udpw->msg_buf = (char *) &udpw[1];
2026  udpw->msg_size = udpmlen; /* message size with UDP overhead */
2027  udpw->payload_size = msgbuf_size; /* message size without UDP overhead */
2031  s->last_transmit_time =
2034  udpw->cont = cont;
2035  udpw->cont_cls = cont_cls;
2036  udpw->frag_ctx = NULL;
2037  udpw->qc = &qc_message_sent;
2038  udpw->qc_cls = plugin;
2039  GNUNET_memcpy (udpw->msg_buf, udp, sizeof(struct UDPMessage));
2040  GNUNET_memcpy (&udpw->msg_buf[sizeof(struct UDPMessage)],
2041  msgbuf,
2042  msgbuf_size);
2043  enqueue (plugin, udpw);
2044  GNUNET_STATISTICS_update (plugin->env->stats,
2045  "# UDP, unfragmented messages queued total",
2046  1,
2047  GNUNET_NO);
2048  GNUNET_STATISTICS_update (plugin->env->stats,
2049  "# UDP, unfragmented bytes payload queued total",
2050  msgbuf_size,
2051  GNUNET_NO);
2052  if (s->address->address_length == sizeof(struct IPv4UdpAddress))
2054  else
2056  }
2057  else
2058  {
2059  /* fragmented message */
2060  if (NULL != s->frag_ctx)
2061  return GNUNET_SYSERR;
2062  GNUNET_memcpy (&udp[1], msgbuf, msgbuf_size);
2063  frag_ctx = GNUNET_new (struct UDP_FragmentationContext);
2064  frag_ctx->plugin = plugin;
2065  frag_ctx->session = s;
2066  frag_ctx->cont = cont;
2067  frag_ctx->cont_cls = cont_cls;
2068  frag_ctx->start_time = GNUNET_TIME_absolute_get ();
2069  frag_ctx->next_frag_time = s->last_transmit_time;
2070  frag_ctx->flow_delay_from_other_peer =
2072  1 + (msgbuf_size / UDP_MTU));
2073  frag_ctx->timeout = GNUNET_TIME_relative_to_absolute (to);
2074  frag_ctx->payload_size =
2075  msgbuf_size; /* unfragmented message size without UDP overhead */
2076  frag_ctx->on_wire_size = 0; /* bytes with UDP and fragmentation overhead */
2077  frag_ctx->frag = GNUNET_FRAGMENT_context_create (plugin->env->stats,
2078  UDP_MTU,
2079  &plugin->tracker,
2082  &udp->header,
2084  frag_ctx);
2085  s->frag_ctx = frag_ctx;
2086  s->last_transmit_time = frag_ctx->next_frag_time;
2088  if (latency.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
2090  "Enqueued fragments will take %s for transmission to %s (queue size: %u)\n",
2092  GNUNET_i2s (&s->target),
2093  (unsigned int) s->msgs_in_queue);
2094  else
2096  "Enqueued fragments will take %s for transmission to %s (queue size: %u)\n",
2098  GNUNET_i2s (&s->target),
2099  (unsigned int) s->msgs_in_queue);
2100 
2101  GNUNET_STATISTICS_update (plugin->env->stats,
2102  "# UDP, fragmented messages active",
2103  1,
2104  GNUNET_NO);
2105  GNUNET_STATISTICS_update (plugin->env->stats,
2106  "# UDP, fragmented messages, total",
2107  1,
2108  GNUNET_NO);
2109  GNUNET_STATISTICS_update (plugin->env->stats,
2110  "# UDP, fragmented bytes (payload)",
2111  frag_ctx->payload_size,
2112  GNUNET_NO);
2113  }
2115  return udpmlen;
2116 }
2117 
2118 
2119 /* ********************** Receiving ********************** */
2120 
2121 
2126 {
2131 
2136 
2140  const union UdpAddress *udp_addr;
2141 
2146 };
2147 
2148 
2159 static int
2161  struct GNUNET_CONTAINER_HeapNode *node,
2162  void *element,
2164 {
2165  struct FindReceiveContext *frc = cls;
2166  struct DefragContext *e = element;
2167 
2168  if ((frc->udp_addr_len == e->udp_addr_len) &&
2169  (0 == memcmp (frc->udp_addr, e->udp_addr, frc->udp_addr_len)))
2170  {
2171  frc->rc = e;
2172  return GNUNET_NO;
2173  }
2174  return GNUNET_YES;
2175 }
2176 
2177 
2186 static int
2188 {
2189  struct Plugin *plugin = cls;
2190  struct UDP_MessageWrapper *udpw;
2191  struct UDP_MessageWrapper *next;
2192  struct FindReceiveContext frc;
2193 
2196  "Session %p to peer `%s' at address %s ended\n",
2197  s,
2198  GNUNET_i2s (&s->target),
2200  s->address->address,
2201  s->address->address_length));
2202  if (NULL != s->timeout_task)
2203  {
2205  s->timeout_task = NULL;
2206  }
2207  if (NULL != s->frag_ctx)
2208  {
2209  /* Remove fragmented message due to disconnect */
2211  }
2212  GNUNET_assert (
2213  GNUNET_YES ==
2214  GNUNET_CONTAINER_multipeermap_remove (plugin->sessions, &s->target, s));
2215  frc.rc = NULL;
2216  frc.udp_addr = s->address->address;
2218  /* Lookup existing receive context for this address */
2219  if (NULL != plugin->defrag_ctxs)
2220  {
2221  GNUNET_CONTAINER_heap_iterate (plugin->defrag_ctxs,
2223  &frc);
2224  if (NULL != frc.rc)
2225  {
2226  struct DefragContext *d_ctx = frc.rc;
2227 
2230  GNUNET_free (d_ctx);
2231  }
2232  }
2233  s->in_destroy = GNUNET_YES;
2234  next = plugin->ipv4_queue_head;
2235  while (NULL != (udpw = next))
2236  {
2237  next = udpw->next;
2238  if (udpw->session == s)
2239  {
2240  dequeue (plugin, udpw);
2241  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
2242  GNUNET_free (udpw);
2243  }
2244  }
2245  next = plugin->ipv6_queue_head;
2246  while (NULL != (udpw = next))
2247  {
2248  next = udpw->next;
2249  if (udpw->session == s)
2250  {
2251  dequeue (plugin, udpw);
2252  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
2253  GNUNET_free (udpw);
2254  }
2255  }
2256  if ((NULL != s->frag_ctx) && (NULL != s->frag_ctx->cont))
2257  {
2258  /* The 'frag_ctx' itself will be freed in #free_session() a bit
2259  later, as it might be in use right now */
2261  "Calling continuation for fragemented message to `%s' with result SYSERR\n",
2262  GNUNET_i2s (&s->target));
2263  s->frag_ctx->cont (s->frag_ctx->cont_cls,
2264  &s->target,
2265  GNUNET_SYSERR,
2266  s->frag_ctx->payload_size,
2267  s->frag_ctx->on_wire_size);
2268  }
2270  plugin->env->session_end (plugin->env->cls, s->address, s);
2271  GNUNET_STATISTICS_set (plugin->env->stats,
2272  "# UDP sessions active",
2274  GNUNET_NO);
2275  if (0 == s->rc)
2276  free_session (s);
2277  return GNUNET_OK;
2278 }
2279 
2280 
2289 static void
2291  const struct GNUNET_MessageHeader *msg,
2292  const union UdpAddress *udp_addr,
2293  socklen_t udp_addr_len)
2294 {
2295  const struct GNUNET_MessageHeader *ack;
2296  const struct UDP_ACK_Message *udp_ack;
2297  struct GNUNET_HELLO_Address *address;
2298  struct GNUNET_ATS_Session *s;
2299  struct GNUNET_TIME_Relative flow_delay;
2300 
2301  /* check message format */
2302  if (ntohs (msg->size) <
2303  sizeof(struct UDP_ACK_Message) + sizeof(struct GNUNET_MessageHeader))
2304  {
2305  GNUNET_break_op (0);
2306  return;
2307  }
2308  udp_ack = (const struct UDP_ACK_Message *) msg;
2309  ack = (const struct GNUNET_MessageHeader *) &udp_ack[1];
2310  if (ntohs (ack->size) != ntohs (msg->size) - sizeof(struct UDP_ACK_Message))
2311  {
2312  GNUNET_break_op (0);
2313  return;
2314  }
2315 
2316  /* Locate session */
2318  PLUGIN_NAME,
2319  udp_addr,
2320  udp_addr_len,
2323  if (NULL == s)
2324  {
2326  "UDP session of address %s for ACK not found\n",
2328  address->address,
2329  address->address_length));
2331  return;
2332  }
2333  if (NULL == s->frag_ctx)
2334  {
2336  "Fragmentation context of address %s for ACK (%s) not found\n",
2338  address->address,
2339  address->address_length),
2342  return;
2343  }
2345 
2346  /* evaluate flow delay: how long should we wait between messages? */
2347  if (UINT32_MAX == ntohl (udp_ack->delay))
2348  {
2349  /* Other peer asked for us to terminate the session */
2351  "Asked to disconnect UDP session of %s\n",
2352  GNUNET_i2s (&udp_ack->sender));
2354  return;
2355  }
2356  flow_delay.rel_value_us = (uint64_t) ntohl (udp_ack->delay);
2357  if (flow_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
2359  "We received a sending delay of %s for %s\n",
2361  GNUNET_i2s (&udp_ack->sender));
2362  else
2364  "We received a sending delay of %s for %s\n",
2366  GNUNET_i2s (&udp_ack->sender));
2367  /* Flow delay is for the reassembled packet, however, our delay
2368  is per packet, so we need to adjust: */
2369  s->flow_delay_from_other_peer = flow_delay;
2370 
2371  /* Handle ACK */
2373  {
2375  "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
2376  (unsigned int) ntohs (msg->size),
2377  GNUNET_i2s (&udp_ack->sender),
2378  udp_address_to_string (plugin, udp_addr, udp_addr_len));
2379  /* Expect more ACKs to arrive */
2380  return;
2381  }
2382 
2383  /* Remove fragmented message after successful sending */
2385  "Message from %s at %s full ACK'ed\n",
2386  GNUNET_i2s (&udp_ack->sender),
2387  udp_address_to_string (plugin, udp_addr, udp_addr_len));
2389 }
2390 
2391 
2400 static int
2402  const struct GNUNET_MessageHeader *hdr)
2403 {
2404  struct GNUNET_ATS_Session *session = cls;
2405  struct Plugin *plugin = session->plugin;
2406 
2407  if (GNUNET_YES == session->in_destroy)
2408  return GNUNET_OK;
2409  reschedule_session_timeout (session);
2410  session->flow_delay_for_other_peer =
2411  plugin->env->receive (plugin->env->cls, session->address, session, hdr);
2412  return GNUNET_OK;
2413 }
2414 
2415 
2424 static int
2426  const struct GNUNET_PeerIdentity *key,
2427  void *value)
2428 {
2429  struct Plugin *plugin = cls;
2430 
2432  return GNUNET_OK;
2433 }
2434 
2435 
2444 static void
2445 udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
2446 {
2447  struct Plugin *plugin = cls;
2448 
2450  "Disconnecting from peer `%s'\n",
2451  GNUNET_i2s (target));
2453  target,
2455  plugin);
2456 }
2457 
2458 
2464 static void
2465 session_timeout (void *cls)
2466 {
2467  struct GNUNET_ATS_Session *s = cls;
2468  struct Plugin *plugin = s->plugin;
2469  struct GNUNET_TIME_Relative left;
2470 
2471  s->timeout_task = NULL;
2473  if (left.rel_value_us > 0)
2474  {
2475  /* not actually our turn yet, but let's at least update
2476  the monitor, it may think we're about to die ... */
2479  return;
2480  }
2482  "Session %p was idle for %s, disconnecting\n",
2483  s,
2485  GNUNET_YES));
2486  /* call session destroy function */
2488 }
2489 
2490 
2502 static struct GNUNET_ATS_Session *
2504  const struct GNUNET_HELLO_Address *address,
2505  enum GNUNET_NetworkType network_type)
2506 {
2507  struct Plugin *plugin = cls;
2508  struct GNUNET_ATS_Session *s;
2509 
2510  s = GNUNET_new (struct GNUNET_ATS_Session);
2512  s->plugin = plugin;
2514  s->target = address->peer;
2522  s->timeout_task =
2524  s->scope = network_type;
2525 
2527  "Creating new session %p for peer `%s' address `%s'\n",
2528  s,
2529  GNUNET_i2s (&address->peer),
2531  address->address,
2532  address->address_length));
2534  plugin->sessions,
2535  &s->target,
2536  s,
2538  GNUNET_STATISTICS_set (plugin->env->stats,
2539  "# UDP sessions active",
2541  GNUNET_NO);
2543  return s;
2544 }
2545 
2546 
2555 static struct GNUNET_ATS_Session *
2557 {
2558  struct Plugin *plugin = cls;
2559  struct GNUNET_ATS_Session *s;
2560  enum GNUNET_NetworkType network_type = GNUNET_NT_UNSPECIFIED;
2561  const struct IPv4UdpAddress *udp_v4;
2562  const struct IPv6UdpAddress *udp_v6;
2563 
2564  if (NULL == address)
2565  {
2566  GNUNET_break (0);
2567  return NULL;
2568  }
2569  if ((address->address_length != sizeof(struct IPv4UdpAddress)) &&
2570  (address->address_length != sizeof(struct IPv6UdpAddress)))
2571  {
2572  GNUNET_break_op (0);
2573  return NULL;
2574  }
2575  if (NULL != (s = udp_plugin_lookup_session (cls, address)))
2576  return s;
2577 
2578  /* need to create new session */
2579  if (sizeof(struct IPv4UdpAddress) == address->address_length)
2580  {
2581  struct sockaddr_in v4;
2582 
2583  udp_v4 = (const struct IPv4UdpAddress *) address->address;
2584  memset (&v4, '\0', sizeof(v4));
2585  v4.sin_family = AF_INET;
2586 #if HAVE_SOCKADDR_IN_SIN_LEN
2587  v4.sin_len = sizeof(struct sockaddr_in);
2588 #endif
2589  v4.sin_port = udp_v4->u4_port;
2590  v4.sin_addr.s_addr = udp_v4->ipv4_addr;
2591  network_type = plugin->env->get_address_type (plugin->env->cls,
2592  (const struct sockaddr *) &v4,
2593  sizeof(v4));
2594  }
2595  if (sizeof(struct IPv6UdpAddress) == address->address_length)
2596  {
2597  struct sockaddr_in6 v6;
2598 
2599  udp_v6 = (const struct IPv6UdpAddress *) address->address;
2600  memset (&v6, '\0', sizeof(v6));
2601  v6.sin6_family = AF_INET6;
2602 #if HAVE_SOCKADDR_IN_SIN_LEN
2603  v6.sin6_len = sizeof(struct sockaddr_in6);
2604 #endif
2605  v6.sin6_port = udp_v6->u6_port;
2606  v6.sin6_addr = udp_v6->ipv6_addr;
2607  network_type = plugin->env->get_address_type (plugin->env->cls,
2608  (const struct sockaddr *) &v6,
2609  sizeof(v6));
2610  }
2611  GNUNET_break (GNUNET_NT_UNSPECIFIED != network_type);
2612  return udp_plugin_create_session (cls, address, network_type);
2613 }
2614 
2615 
2625 static void
2627  const struct UDPMessage *msg,
2628  const union UdpAddress *udp_addr,
2629  size_t udp_addr_len,
2630  enum GNUNET_NetworkType network_type)
2631 {
2632  struct GNUNET_ATS_Session *s;
2633  struct GNUNET_HELLO_Address *address;
2634 
2635  GNUNET_break (GNUNET_NT_UNSPECIFIED != network_type);
2636  if (0 != ntohl (msg->reserved))
2637  {
2638  GNUNET_break_op (0);
2639  return;
2640  }
2641  if (ntohs (msg->header.size) <
2642  sizeof(struct GNUNET_MessageHeader) + sizeof(struct UDPMessage))
2643  {
2644  GNUNET_break_op (0);
2645  return;
2646  }
2647 
2649  PLUGIN_NAME,
2650  udp_addr,
2651  udp_addr_len,
2653  if (NULL == (s = udp_plugin_lookup_session (plugin, address)))
2654  {
2655  s = udp_plugin_create_session (plugin, address, network_type);
2656  plugin->env->session_start (plugin->env->cls, address, s, s->scope);
2658  }
2659  GNUNET_free (address);
2660 
2661  s->rc++;
2663  (const char *) &msg[1],
2664  ntohs (msg->header.size) - sizeof(struct UDPMessage),
2665  GNUNET_YES,
2666  GNUNET_NO);
2667  s->rc--;
2668  if ((0 == s->rc) && (GNUNET_YES == s->in_destroy))
2669  free_session (s);
2670 }
2671 
2672 
2679 static void
2680 fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg)
2681 {
2682  struct DefragContext *dc = cls;
2683  const struct UDPMessage *um;
2684 
2686  {
2687  GNUNET_break_op (0);
2688  return;
2689  }
2690  if (ntohs (msg->size) < sizeof(struct UDPMessage))
2691  {
2692  GNUNET_break_op (0);
2693  return;
2694  }
2695  um = (const struct UDPMessage *) msg;
2696  dc->sender = um->sender;
2697  dc->have_sender = GNUNET_YES;
2698  process_udp_message (dc->plugin,
2699  um,
2700  dc->udp_addr,
2701  dc->udp_addr_len,
2702  dc->network_type);
2703 }
2704 
2705 
2715 static void
2716 ack_message_sent (void *cls, struct UDP_MessageWrapper *udpw, int result)
2717 {
2718  struct Plugin *plugin = cls;
2719 
2720  if (GNUNET_OK == result)
2721  {
2722  GNUNET_STATISTICS_update (plugin->env->stats,
2723  "# UDP, ACK messages sent",
2724  1,
2725  GNUNET_NO);
2726  }
2727  else
2728  {
2729  GNUNET_STATISTICS_update (plugin->env->stats,
2730  "# UDP, ACK transmissions failed",
2731  1,
2732  GNUNET_NO);
2733  }
2734 }
2735 
2736 
2744 static void
2745 ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
2746 {
2747  struct DefragContext *rc = cls;
2748  struct Plugin *plugin = rc->plugin;
2749  size_t msize = sizeof(struct UDP_ACK_Message) + ntohs (msg->size);
2750  struct UDP_ACK_Message *udp_ack;
2751  uint32_t delay;
2752  struct UDP_MessageWrapper *udpw;
2753  struct GNUNET_ATS_Session *s;
2754  struct GNUNET_HELLO_Address *address;
2755 
2756  if (GNUNET_NO == rc->have_sender)
2757  {
2758  /* tried to defragment but never succeeded, hence will not ACK */
2759  /* This can happen if we just lost msgs */
2760  GNUNET_STATISTICS_update (plugin->env->stats,
2761  "# UDP, fragments discarded without ACK",
2762  1,
2763  GNUNET_NO);
2764  return;
2765  }
2767  PLUGIN_NAME,
2768  rc->udp_addr,
2769  rc->udp_addr_len,
2773  if (NULL == s)
2774  {
2776  "Trying to transmit ACK to peer `%s' but no session found!\n",
2780  GNUNET_free (rc);
2781  GNUNET_STATISTICS_update (plugin->env->stats,
2782  "# UDP, ACK transmissions failed",
2783  1,
2784  GNUNET_NO);
2785  return;
2786  }
2787  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us ==
2789  delay = UINT32_MAX;
2790  else if (s->flow_delay_for_other_peer.rel_value_us < UINT32_MAX)
2792  else
2793  delay = UINT32_MAX - 1; /* largest value we can communicate */
2795  "Sending ACK to `%s' including delay of %s\n",
2798  GNUNET_YES));
2799  udpw = GNUNET_malloc (sizeof(struct UDP_MessageWrapper) + msize);
2800  udpw->msg_size = msize;
2801  udpw->payload_size = 0;
2802  udpw->session = s;
2805  udpw->msg_buf = (char *) &udpw[1];
2806  udpw->qc = &ack_message_sent;
2807  udpw->qc_cls = plugin;
2808  udp_ack = (struct UDP_ACK_Message *) udpw->msg_buf;
2809  udp_ack->header.size = htons ((uint16_t) msize);
2811  udp_ack->delay = htonl (delay);
2812  udp_ack->sender = *plugin->env->my_identity;
2813  GNUNET_memcpy (&udp_ack[1], msg, ntohs (msg->size));
2814  enqueue (plugin, udpw);
2816  if (s->address->address_length == sizeof(struct IPv4UdpAddress))
2818  else
2820 }
2821 
2822 
2832 static void
2834  const struct GNUNET_MessageHeader *msg,
2835  const union UdpAddress *udp_addr,
2836  size_t udp_addr_len,
2837  enum GNUNET_NetworkType network_type)
2838 {
2839  struct DefragContext *d_ctx;
2840  struct GNUNET_TIME_Absolute now;
2841  struct FindReceiveContext frc;
2842 
2843  frc.rc = NULL;
2844  frc.udp_addr = udp_addr;
2845  frc.udp_addr_len = udp_addr_len;
2846 
2847  /* Lookup existing receive context for this address */
2848  GNUNET_CONTAINER_heap_iterate (plugin->defrag_ctxs,
2850  &frc);
2851  now = GNUNET_TIME_absolute_get ();
2852  d_ctx = frc.rc;
2853 
2854  if (NULL == d_ctx)
2855  {
2856  /* Create a new defragmentation context */
2857  d_ctx = GNUNET_malloc (sizeof(struct DefragContext) + udp_addr_len);
2858  GNUNET_memcpy (&d_ctx[1], udp_addr, udp_addr_len);
2859  d_ctx->udp_addr = (const union UdpAddress *) &d_ctx[1];
2860  d_ctx->udp_addr_len = udp_addr_len;
2861  d_ctx->network_type = network_type;
2862  d_ctx->plugin = plugin;
2863  d_ctx->defrag =
2865  UDP_MTU,
2867  d_ctx,
2869  &ack_proc);
2870  d_ctx->hnode = GNUNET_CONTAINER_heap_insert (plugin->defrag_ctxs,
2871  d_ctx,
2873  now.abs_value_us);
2875  "Created new defragmentation context for %u-byte fragment from `%s'\n",
2876  (unsigned int) ntohs (msg->size),
2877  udp_address_to_string (plugin, udp_addr, udp_addr_len));
2878  }
2879  else
2880  {
2882  "Found existing defragmentation context for %u-byte fragment from `%s'\n",
2883  (unsigned int) ntohs (msg->size),
2884  udp_address_to_string (plugin, udp_addr, udp_addr_len));
2885  }
2886 
2888  {
2889  /* keep this 'rc' from expiring */
2892  now.abs_value_us);
2893  }
2894  if (GNUNET_CONTAINER_heap_get_size (plugin->defrag_ctxs) >
2896  {
2897  /* remove 'rc' that was inactive the longest */
2898  d_ctx = GNUNET_CONTAINER_heap_remove_root (plugin->defrag_ctxs);
2899  GNUNET_assert (NULL != d_ctx);
2901  GNUNET_free (d_ctx);
2902  GNUNET_STATISTICS_update (plugin->env->stats,
2903  "# UDP, Defragmentations aborted",
2904  1,
2905  GNUNET_NO);
2906  }
2907 }
2908 
2909 
2916 static void
2918 {
2919  socklen_t fromlen;
2920  struct sockaddr_storage addr;
2921  char buf[65536] GNUNET_ALIGN;
2922  ssize_t size;
2923  const struct GNUNET_MessageHeader *msg;
2924  struct IPv4UdpAddress v4;
2925  struct IPv6UdpAddress v6;
2926  const struct sockaddr *sa;
2927  const struct sockaddr_in *sa4;
2928  const struct sockaddr_in6 *sa6;
2929  const union UdpAddress *int_addr;
2930  size_t int_addr_len;
2931  enum GNUNET_NetworkType network_type;
2932 
2933  fromlen = sizeof(addr);
2934  memset (&addr, 0, sizeof(addr));
2936  buf,
2937  sizeof(buf),
2938  (struct sockaddr *) &addr,
2939  &fromlen);
2940  sa = (const struct sockaddr *) &addr;
2941 
2942  if (-1 == size)
2943  {
2945  "UDP failed to receive data: %s\n",
2946  strerror (errno));
2947  /* Connection failure or something. Not a protocol violation. */
2948  return;
2949  }
2950 
2951  /* Check if this is a STUN packet */
2952  if (GNUNET_NO !=
2954  (const struct sockaddr *) &addr,
2955  fromlen,
2956  buf,
2957  size))
2958  return; /* was STUN, do not process further */
2959 
2960  if (size < sizeof(struct GNUNET_MessageHeader))
2961  {
2963  "UDP got %u bytes from %s, which is not enough for a GNUnet message header\n",
2964  (unsigned int) size,
2965  GNUNET_a2s (sa, fromlen));
2966  /* _MAY_ be a connection failure (got partial message) */
2967  /* But it _MAY_ also be that the other side uses non-GNUnet protocol. */
2968  GNUNET_break_op (0);
2969  return;
2970  }
2971 
2972  msg = (const struct GNUNET_MessageHeader *) buf;
2974  "UDP received %u-byte message from `%s' type %u\n",
2975  (unsigned int) size,
2976  GNUNET_a2s (sa, fromlen),
2977  ntohs (msg->type));
2978  if (size != ntohs (msg->size))
2979  {
2981  "UDP malformed message (size %u) header from %s\n",
2982  (unsigned int) size,
2983  GNUNET_a2s (sa, fromlen));
2984  GNUNET_break_op (0);
2985  return;
2986  }
2987  GNUNET_STATISTICS_update (plugin->env->stats,
2988  "# UDP, total bytes received",
2989  size,
2990  GNUNET_NO);
2991  network_type = plugin->env->get_address_type (plugin->env->cls, sa, fromlen);
2992  switch (sa->sa_family)
2993  {
2994  case AF_INET:
2995  sa4 = (const struct sockaddr_in *) &addr;
2996  v4.options = 0;
2997  v4.ipv4_addr = sa4->sin_addr.s_addr;
2998  v4.u4_port = sa4->sin_port;
2999  int_addr = (union UdpAddress *) &v4;
3000  int_addr_len = sizeof(v4);
3001  break;
3002 
3003  case AF_INET6:
3004  sa6 = (const struct sockaddr_in6 *) &addr;
3005  v6.options = 0;
3006  v6.ipv6_addr = sa6->sin6_addr;
3007  v6.u6_port = sa6->sin6_port;
3008  int_addr = (union UdpAddress *) &v6;
3009  int_addr_len = sizeof(v6);
3010  break;
3011 
3012  default:
3013  GNUNET_break (0);
3014  return;
3015  }
3016 
3017  switch (ntohs (msg->type))
3018  {
3020  if (GNUNET_YES == plugin->enable_broadcasting_receiving)
3022  buf,
3023  size,
3024  int_addr,
3025  int_addr_len,
3026  network_type);
3027  return;
3028 
3030  if (ntohs (msg->size) < sizeof(struct UDPMessage))
3031  {
3032  GNUNET_break_op (0);
3033  return;
3034  }
3036  (const struct UDPMessage *) msg,
3037  int_addr,
3038  int_addr_len,
3039  network_type);
3040  return;
3041 
3043  read_process_ack (plugin, msg, int_addr, int_addr_len);
3044  return;
3045 
3047  read_process_fragment (plugin, msg, int_addr, int_addr_len, network_type);
3048  return;
3049 
3050  default:
3051  GNUNET_break_op (0);
3052  return;
3053  }
3054 }
3055 
3056 
3066 static struct UDP_MessageWrapper *
3068  struct GNUNET_NETWORK_Handle *sock)
3069 {
3070  struct UDP_MessageWrapper *udpw;
3071  struct GNUNET_TIME_Relative remaining;
3072  struct GNUNET_ATS_Session *session;
3073  int removed;
3074 
3075  removed = GNUNET_NO;
3076  udpw = (sock == plugin->sockv4) ? plugin->ipv4_queue_head
3077  : plugin->ipv6_queue_head;
3078  while (NULL != udpw)
3079  {
3080  session = udpw->session;
3081  /* Find messages with timeout */
3082  remaining = GNUNET_TIME_absolute_get_remaining (udpw->timeout);
3083  if (GNUNET_TIME_UNIT_ZERO.rel_value_us == remaining.rel_value_us)
3084  {
3085  /* Message timed out */
3086  removed = GNUNET_YES;
3087  dequeue (plugin, udpw);
3088  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
3089  GNUNET_free (udpw);
3090 
3091  if (sock == plugin->sockv4)
3092  {
3093  udpw = plugin->ipv4_queue_head;
3094  }
3095  else if (sock == plugin->sockv6)
3096  {
3097  udpw = plugin->ipv6_queue_head;
3098  }
3099  else
3100  {
3101  GNUNET_break (0); /* should never happen */
3102  udpw = NULL;
3103  }
3104  GNUNET_STATISTICS_update (plugin->env->stats,
3105  "# messages discarded due to timeout",
3106  1,
3107  GNUNET_NO);
3108  }
3109  else
3110  {
3111  /* Message did not time out, check transmission time */
3113  if (0 == remaining.rel_value_us)
3114  {
3115  /* this message is not delayed */
3117  "Message for peer `%s' (%lu bytes) is not delayed \n",
3118  GNUNET_i2s (&udpw->session->target),
3119  (unsigned long) udpw->payload_size);
3120  break; /* Found message to send, break */
3121  }
3122  else
3123  {
3124  /* Message is delayed, try next */
3126  "Message for peer `%s' (%lu bytes) is delayed for %s\n",
3127  GNUNET_i2s (&udpw->session->target),
3128  (unsigned long) udpw->payload_size,
3130  udpw = udpw->next;
3131  }
3132  }
3133  }
3134  if (GNUNET_YES == removed)
3135  notify_session_monitor (session->plugin,
3136  session,
3138  return udpw;
3139 }
3140 
3141 
3151 static void
3153  const struct sockaddr *sa,
3154  socklen_t slen,
3155  int error)
3156 {
3157  enum GNUNET_NetworkType type;
3158 
3159  type = plugin->env->get_address_type (plugin->env->cls, sa, slen);
3160  if (((GNUNET_NT_LAN == type) || (GNUNET_NT_WAN == type)) &&
3161  ((ENETUNREACH == errno) || (ENETDOWN == errno)))
3162  {
3163  if (slen == sizeof(struct sockaddr_in))
3164  {
3165  /* IPv4: "Network unreachable" or "Network down"
3166  *
3167  * This indicates we do not have connectivity
3168  */
3170  _ ("UDP could not transmit message to `%s': "
3171  "Network seems down, please check your network configuration\n"),
3172  GNUNET_a2s (sa, slen));
3173  }
3174  if (slen == sizeof(struct sockaddr_in6))
3175  {
3176  /* IPv6: "Network unreachable" or "Network down"
3177  *
3178  * This indicates that this system is IPv6 enabled, but does not
3179  * have a valid global IPv6 address assigned or we do not have
3180  * connectivity
3182  _ (
3183  "UDP could not transmit IPv6 message! "
3184  "Please check your network configuration and disable IPv6 if your "
3185  "connection does not have a global IPv6 address\n"));
3186  }
3187  }
3188  else
3189  {
3191  "UDP could not transmit message to `%s': `%s'\n",
3192  GNUNET_a2s (sa, slen),
3193  strerror (error));
3194  }
3195 }
3196 
3197 
3205 static void
3207 {
3208  ssize_t sent;
3209  socklen_t slen;
3210  const struct sockaddr *a;
3211  const struct IPv4UdpAddress *u4;
3212  struct sockaddr_in a4;
3213  const struct IPv6UdpAddress *u6;
3214  struct sockaddr_in6 a6;
3215  struct UDP_MessageWrapper *udpw;
3216 
3217  /* Find message(s) to send */
3218  while (NULL != (udpw = remove_timeout_messages_and_select (plugin, sock)))
3219  {
3220  if (sizeof(struct IPv4UdpAddress) ==
3221  udpw->session->address->address_length)
3222  {
3223  u4 = udpw->session->address->address;
3224  memset (&a4, 0, sizeof(a4));
3225  a4.sin_family = AF_INET;
3226 #if HAVE_SOCKADDR_IN_SIN_LEN
3227  a4.sin_len = sizeof(a4);
3228 #endif
3229  a4.sin_port = u4->u4_port;
3230  a4.sin_addr.s_addr = u4->ipv4_addr;
3231  a = (const struct sockaddr *) &a4;
3232  slen = sizeof(a4);
3233  }
3234  else if (sizeof(struct IPv6UdpAddress) ==
3235  udpw->session->address->address_length)
3236  {
3237  u6 = udpw->session->address->address;
3238  memset (&a6, 0, sizeof(a6));
3239  a6.sin6_family = AF_INET6;
3240 #if HAVE_SOCKADDR_IN_SIN_LEN
3241  a6.sin6_len = sizeof(a6);
3242 #endif
3243  a6.sin6_port = u6->u6_port;
3244  a6.sin6_addr = u6->ipv6_addr;
3245  a = (const struct sockaddr *) &a6;
3246  slen = sizeof(a6);
3247  }
3248  else
3249  {
3250  GNUNET_break (0);
3251  dequeue (plugin, udpw);
3252  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
3254  udpw->session,
3256  GNUNET_free (udpw);
3257  continue;
3258  }
3259  sent = GNUNET_NETWORK_socket_sendto (sock,
3260  udpw->msg_buf,
3261  udpw->msg_size,
3262  a,
3263  slen);
3264  udpw->session->last_transmit_time =
3266  udpw->session->last_transmit_time);
3267  dequeue (plugin, udpw);
3268  if (GNUNET_SYSERR == sent)
3269  {
3270  /* Failure */
3271  analyze_send_error (plugin, a, slen, errno);
3272  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
3273  GNUNET_STATISTICS_update (plugin->env->stats,
3274  "# UDP, total, bytes, sent, failure",
3275  sent,
3276  GNUNET_NO);
3277  GNUNET_STATISTICS_update (plugin->env->stats,
3278  "# UDP, total, messages, sent, failure",
3279  1,
3280  GNUNET_NO);
3281  }
3282  else
3283  {
3284  /* Success */
3286  "UDP transmitted %u-byte message to `%s' `%s' (%d: %s)\n",
3287  (unsigned int) (udpw->msg_size),
3288  GNUNET_i2s (&udpw->session->target),
3289  GNUNET_a2s (a, slen),
3290  (int) sent,
3291  (sent < 0) ? strerror (errno) : "ok");
3292  GNUNET_STATISTICS_update (plugin->env->stats,
3293  "# UDP, total, bytes, sent, success",
3294  sent,
3295  GNUNET_NO);
3296  GNUNET_STATISTICS_update (plugin->env->stats,
3297  "# UDP, total, messages, sent, success",
3298  1,
3299  GNUNET_NO);
3300  if (NULL != udpw->frag_ctx)
3301  udpw->frag_ctx->on_wire_size += udpw->msg_size;
3302  udpw->qc (udpw->qc_cls, udpw, GNUNET_OK);
3303  }
3305  GNUNET_free (udpw);
3306  }
3307 }
3308 
3309 
3310 /* ***************** Event loop (part 2) *************** */
3311 
3312 
3320 static void
3322 {
3323  struct Plugin *plugin = cls;
3324  const struct GNUNET_SCHEDULER_TaskContext *tc;
3325 
3326  plugin->select_task_v4 = NULL;
3327  if (NULL == plugin->sockv4)
3328  return;
3330  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
3332  udp_select_read (plugin, plugin->sockv4);
3333  udp_select_send (plugin, plugin->sockv4);
3335 }
3336 
3337 
3345 static void
3347 {
3348  struct Plugin *plugin = cls;
3349  const struct GNUNET_SCHEDULER_TaskContext *tc;
3350 
3351  plugin->select_task_v6 = NULL;
3352  if (NULL == plugin->sockv6)
3353  return;
3355  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
3357  udp_select_read (plugin, plugin->sockv6);
3358 
3359  udp_select_send (plugin, plugin->sockv6);
3361 }
3362 
3363 
3364 /* ******************* Initialization *************** */
3365 
3366 
3375 static unsigned int
3377  const struct sockaddr_in6 *bind_v6,
3378  const struct sockaddr_in *bind_v4)
3379 {
3380  int tries;
3381  unsigned int sockets_created = 0;
3382  struct sockaddr_in6 server_addrv6;
3383  struct sockaddr_in server_addrv4;
3384  const struct sockaddr *server_addr;
3385  const struct sockaddr *addrs[2];
3386  socklen_t addrlens[2];
3387  socklen_t addrlen;
3388  int eno;
3389 
3390  /* Create IPv6 socket */
3391  eno = EINVAL;
3392  if (GNUNET_YES == plugin->enable_ipv6)
3393  {
3394  plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
3395  if (NULL == plugin->sockv6)
3396  {
3398  _ ("Disabling IPv6 since it is not supported on this system!\n"));
3399  plugin->enable_ipv6 = GNUNET_NO;
3400  }
3401  else
3402  {
3403  memset (&server_addrv6, 0, sizeof(struct sockaddr_in6));
3404 #if HAVE_SOCKADDR_IN_SIN_LEN
3405  server_addrv6.sin6_len = sizeof(struct sockaddr_in6);
3406 #endif
3407  server_addrv6.sin6_family = AF_INET6;
3408  if (NULL != bind_v6)
3409  server_addrv6.sin6_addr = bind_v6->sin6_addr;
3410  else
3411  server_addrv6.sin6_addr = in6addr_any;
3412 
3413  if (0 == plugin->port) /* autodetect */
3414  server_addrv6.sin6_port = htons (
3416  + 32000);
3417  else
3418  server_addrv6.sin6_port = htons (plugin->port);
3419  addrlen = sizeof(struct sockaddr_in6);
3420  server_addr = (const struct sockaddr *) &server_addrv6;
3421 
3422  tries = 0;
3423  while (tries < 10)
3424  {
3426  "Binding to IPv6 `%s'\n",
3427  GNUNET_a2s (server_addr, addrlen));
3428  /* binding */
3429  if (GNUNET_OK ==
3430  GNUNET_NETWORK_socket_bind (plugin->sockv6, server_addr, addrlen))
3431  break;
3432  eno = errno;
3433  if (0 != plugin->port)
3434  {
3435  tries = 10; /* fail immediately */
3436  break; /* bind failed on specific port */
3437  }
3438  /* autodetect */
3439  server_addrv6.sin6_port = htons (
3441  + 32000);
3442  tries++;
3443  }
3444  if (tries >= 10)
3445  {
3447  plugin->enable_ipv6 = GNUNET_NO;
3448  plugin->sockv6 = NULL;
3449  }
3450  else
3451  {
3452  plugin->port = ntohs (server_addrv6.sin6_port);
3453  }
3454  if (NULL != plugin->sockv6)
3455  {
3457  "IPv6 UDP socket created listinging at %s\n",
3458  GNUNET_a2s (server_addr, addrlen));
3459  addrs[sockets_created] = server_addr;
3460  addrlens[sockets_created] = addrlen;
3461  sockets_created++;
3462  }
3463  else
3464  {
3466  _ ("Failed to bind UDP socket to %s: %s\n"),
3467  GNUNET_a2s (server_addr, addrlen),
3468  strerror (eno));
3469  }
3470  }
3471  }
3472 
3473  /* Create IPv4 socket */
3474  eno = EINVAL;
3475  plugin->sockv4 = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
3476  if (NULL == plugin->sockv4)
3477  {
3480  _ ("Disabling IPv4 since it is not supported on this system!\n"));
3481  plugin->enable_ipv4 = GNUNET_NO;
3482  }
3483  else
3484  {
3485  memset (&server_addrv4, 0, sizeof(struct sockaddr_in));
3486 #if HAVE_SOCKADDR_IN_SIN_LEN
3487  server_addrv4.sin_len = sizeof(struct sockaddr_in);
3488 #endif
3489  server_addrv4.sin_family = AF_INET;
3490  if (NULL != bind_v4)
3491  server_addrv4.sin_addr = bind_v4->sin_addr;
3492  else
3493  server_addrv4.sin_addr.s_addr = INADDR_ANY;
3494 
3495  if (0 == plugin->port)
3496  /* autodetect */
3497  server_addrv4.sin_port = htons (
3499  else
3500  server_addrv4.sin_port = htons (plugin->port);
3501 
3502  addrlen = sizeof(struct sockaddr_in);
3503  server_addr = (const struct sockaddr *) &server_addrv4;
3504 
3505  tries = 0;
3506  while (tries < 10)
3507  {
3509  "Binding to IPv4 `%s'\n",
3510  GNUNET_a2s (server_addr, addrlen));
3511 
3512  /* binding */
3513  if (GNUNET_OK ==
3514  GNUNET_NETWORK_socket_bind (plugin->sockv4, server_addr, addrlen))
3515  break;
3516  eno = errno;
3517  if (0 != plugin->port)
3518  {
3519  tries = 10; /* fail */
3520  break; /* bind failed on specific port */
3521  }
3522 
3523  /* autodetect */
3524  server_addrv4.sin_port = htons (
3526  tries++;
3527  }
3528  if (tries >= 10)
3529  {
3531  plugin->enable_ipv4 = GNUNET_NO;
3532  plugin->sockv4 = NULL;
3533  }
3534  else
3535  {
3536  plugin->port = ntohs (server_addrv4.sin_port);
3537  }
3538 
3539  if (NULL != plugin->sockv4)
3540  {
3542  "IPv4 socket created on port %s\n",
3543  GNUNET_a2s (server_addr, addrlen));
3544  addrs[sockets_created] = server_addr;
3545  addrlens[sockets_created] = addrlen;
3546  sockets_created++;
3547  }
3548  else
3549  {
3551  _ ("Failed to bind UDP socket to %s: %s\n"),
3552  GNUNET_a2s (server_addr, addrlen),
3553  strerror (eno));
3554  }
3555  }
3556 
3557  if (0 == sockets_created)
3558  {
3559  LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Failed to open UDP sockets\n"));
3560  return 0; /* No sockets created, return */
3561  }
3564  plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
3565  "transport-udp",
3566  IPPROTO_UDP,
3567  sockets_created,
3568  addrs,
3569  addrlens,
3571  NULL,
3572  plugin);
3573  return sockets_created;
3574 }
3575 
3576 
3584 void *
3586 {
3589  struct Plugin *p;
3590  unsigned long long port;
3591  unsigned long long aport;
3592  unsigned long long udp_max_bps;
3593  int enable_v6;
3594  int enable_broadcasting;
3595  int enable_broadcasting_recv;
3596  char *bind4_address;
3597  char *bind6_address;
3599  struct sockaddr_in server_addrv4;
3600  struct sockaddr_in6 server_addrv6;
3601  unsigned int res;
3602  int have_bind4;
3603  int have_bind6;
3604 
3605  if (NULL == env->receive)
3606  {
3607  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
3608  initialize the plugin or the API */
3610  api->cls = NULL;
3614  return api;
3615  }
3616 
3617  /* Get port number: port == 0 : autodetect a port,
3618  * > 0 : use this port, not given : 2086 default */
3620  "transport-udp",
3621  "PORT",
3622  &port))
3623  port = 2086;
3624  if (port > 65535)
3625  {
3627  "transport-udp",
3628  "PORT",
3629  _ ("must be in [0,65535]"));
3630  return NULL;
3631  }
3633  "transport-udp",
3634  "ADVERTISED_PORT",
3635  &aport))
3636  aport = port;
3637  if (aport > 65535)
3638  {
3640  "transport-udp",
3641  "ADVERTISED_PORT",
3642  _ ("must be in [0,65535]"));
3643  return NULL;
3644  }
3645 
3646  if (GNUNET_YES ==
3647  GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "nat", "DISABLEV6"))
3648  enable_v6 = GNUNET_NO;
3649  else
3650  enable_v6 = GNUNET_YES;
3651 
3652  have_bind4 = GNUNET_NO;
3653  memset (&server_addrv4, 0, sizeof(server_addrv4));
3655  "transport-udp",
3656  "BINDTO",
3657  &bind4_address))
3658  {
3660  "Binding UDP plugin to specific address: `%s'\n",
3661  bind4_address);
3662  if (1 != inet_pton (AF_INET, bind4_address, &server_addrv4.sin_addr))
3663  {
3665  "transport-udp",
3666  "BINDTO",
3667  _ ("must be valid IPv4 address"));
3668  GNUNET_free (bind4_address);
3669  return NULL;
3670  }
3671  have_bind4 = GNUNET_YES;
3672  }
3673  GNUNET_free (bind4_address);
3674  have_bind6 = GNUNET_NO;
3675  memset (&server_addrv6, 0, sizeof(server_addrv6));
3677  "transport-udp",
3678  "BINDTO6",
3679  &bind6_address))
3680  {
3682  "Binding udp plugin to specific address: `%s'\n",
3683  bind6_address);
3684  if (1 != inet_pton (AF_INET6, bind6_address, &server_addrv6.sin6_addr))
3685  {
3687  "transport-udp",
3688  "BINDTO6",
3689  _ ("must be valid IPv6 address"));
3690  GNUNET_free (bind6_address);
3691  return NULL;
3692  }
3693  have_bind6 = GNUNET_YES;
3694  }
3695  GNUNET_free (bind6_address);
3696 
3697  enable_broadcasting = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
3698  "transport-udp",
3699  "BROADCAST");
3700  if (enable_broadcasting == GNUNET_SYSERR)
3701  enable_broadcasting = GNUNET_NO;
3702 
3703  enable_broadcasting_recv =
3705  "transport-udp",
3706  "BROADCAST_RECEIVE");
3707  if (enable_broadcasting_recv == GNUNET_SYSERR)
3708  enable_broadcasting_recv = GNUNET_YES;
3709 
3710  if (GNUNET_SYSERR ==
3712  "transport-udp",
3713  "BROADCAST_INTERVAL",
3714  &interval))
3715  {
3717  }
3719  "transport-udp",
3720  "MAX_BPS",
3721  &udp_max_bps))
3722  {
3723  /* 50 MB/s == infinity for practical purposes */
3724  udp_max_bps = 1024 * 1024 * 50;
3725  }
3726 
3727  p = GNUNET_new (struct Plugin);
3728  p->port = port;
3729  p->aport = aport;
3730  p->broadcast_interval = interval;
3731  p->enable_ipv6 = enable_v6;
3732  p->enable_ipv4 = GNUNET_YES; /* default */
3733  p->enable_broadcasting = enable_broadcasting;
3734  p->enable_broadcasting_receiving = enable_broadcasting_recv;
3735  p->env = env;
3737  p->defrag_ctxs =
3739  GNUNET_BANDWIDTH_tracker_init (&p->tracker,
3740  NULL,
3741  NULL,
3743  (uint32_t) udp_max_bps),
3744  30);
3745  res = setup_sockets (p,
3746  (GNUNET_YES == have_bind6) ? &server_addrv6 : NULL,
3747  (GNUNET_YES == have_bind4) ? &server_addrv4 : NULL);
3748  if ((0 == res) || ((NULL == p->sockv4) && (NULL == p->sockv6)))
3749  {
3750  LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Failed to create UDP network sockets\n"));
3752  GNUNET_CONTAINER_heap_destroy (p->defrag_ctxs);
3753  if (NULL != p->nat)
3754  GNUNET_NAT_unregister (p->nat);
3755  GNUNET_free (p);
3756  return NULL;
3757  }
3758 
3759  /* Setup broadcasting and receiving beacons */
3760  setup_broadcast (p, &server_addrv6, &server_addrv4);
3761 
3763  api->cls = p;
3772  api->send = &udp_plugin_send;
3777  return api;
3778 }
3779 
3780 
3791 static int
3793  struct GNUNET_CONTAINER_HeapNode *node,
3794  void *element,
3796 {
3797  struct DefragContext *d_ctx = element;
3798 
3801  GNUNET_free (d_ctx);
3802  return GNUNET_YES;
3803 }
3804 
3805 
3813 void *
3815 {
3816  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
3817  struct Plugin *plugin = api->cls;
3818  struct PrettyPrinterContext *cur;
3819  struct UDP_MessageWrapper *udpw;
3820 
3821  if (NULL == plugin)
3822  {
3823  GNUNET_free (api);
3824  return NULL;
3825  }
3827  if (NULL != plugin->select_task_v4)
3828  {
3829  GNUNET_SCHEDULER_cancel (plugin->select_task_v4);
3830  plugin->select_task_v4 = NULL;
3831  }
3832  if (NULL != plugin->select_task_v6)
3833  {
3834  GNUNET_SCHEDULER_cancel (plugin->select_task_v6);
3835  plugin->select_task_v6 = NULL;
3836  }
3837  if (NULL != plugin->sockv4)
3838  {
3840  plugin->sockv4 = NULL;
3841  }
3842  if (NULL != plugin->sockv6)
3843  {
3845  plugin->sockv6 = NULL;
3846  }
3847  if (NULL != plugin->nat)
3848  {
3850  plugin->nat = NULL;
3851  }
3852  if (NULL != plugin->defrag_ctxs)
3853  {
3854  GNUNET_CONTAINER_heap_iterate (plugin->defrag_ctxs,
3856  NULL);
3857  GNUNET_CONTAINER_heap_destroy (plugin->defrag_ctxs);
3858  plugin->defrag_ctxs = NULL;
3859  }
3860  while (NULL != (udpw = plugin->ipv4_queue_head))
3861  {
3862  dequeue (plugin, udpw);
3863  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
3864  GNUNET_free (udpw);
3865  }
3866  while (NULL != (udpw = plugin->ipv6_queue_head))
3867  {
3868  dequeue (plugin, udpw);
3869  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
3870  GNUNET_free (udpw);
3871  }
3874  plugin);
3876 
3877  while (NULL != (cur = plugin->ppc_dll_head))
3878  {
3879  GNUNET_break (0);
3880  GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
3881  plugin->ppc_dll_tail,
3882  cur);
3884  if (NULL != cur->timeout_task)
3885  {
3887  cur->timeout_task = NULL;
3888  }
3889  GNUNET_free (cur);
3890  }
3891  GNUNET_free (plugin);
3892  GNUNET_free (api);
3893  return NULL;
3894 }
3895 
3896 
3897 /* end of plugin_transport_udp.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static struct Experiment * e
static int res
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
struct TestcasePlugin * plugin
The process handle to the testbed service.
static char * address
GNS address for this phone.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_SCHEDULER_Task * t4
Task for IPv4 socket.
static struct GNUNET_SCHEDULER_Task * t6
Task for IPv6 socket.
static struct GNUNET_FS_DownloadContext * dc
static struct GNUNET_NETWORK_Handle * bind_v6()
Create an IPv6 listen socket bound to our port.
static struct GNUNET_NETWORK_Handle * bind_v4()
Create an IPv4 listen socket bound to our port.
static char * value
Value of the record to add/remove.
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
enum State state
current state of profiling
static int result
Global testing status.
#define info
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
static char * hostname
Our hostname; we give this to all the peers we start.
static char buf[2048]
static int numeric
Option -n.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
static int udp
Option -u: UDP requested.
Definition: gnunet-vpn.c:75
Library to help fragment messages.
Helper library for handling HELLOs.
Constants for network protocols.
Functions related to doing DNS lookups.
API to create, modify and access statistics.
Transport service plugin API.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_init(uint32_t bytes_per_second)
Create a new bandwidth value.
Definition: bandwidth.c:40
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:279
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_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.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_CONSTANTS_LATENCY_WARN
After what amount of latency for a message do we print a warning?
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_STRONG
High-quality operations are desired.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
const char * GNUNET_FRAGMENT_print_ack(const struct GNUNET_MessageHeader *ack)
Convert an ACK message to a printable format suitable for logging.
int GNUNET_DEFRAGMENT_process_fragment(struct GNUNET_DEFRAGMENT_Context *dc, const struct GNUNET_MessageHeader *msg)
We have received a fragment.
void GNUNET_FRAGMENT_context_transmission_done(struct GNUNET_FRAGMENT_Context *fc)
Continuation to call from the 'proc' function after the fragment has been transmitted (and hence the ...
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).
void GNUNET_DEFRAGMENT_context_destroy(struct GNUNET_DEFRAGMENT_Context *dc)
Destroy the given defragmentation context.
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.
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 'proc', free resources).
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.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
enum GNUNET_GenericReturnValue 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.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
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.
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.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
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.
uint64_t GNUNET_CONTAINER_HeapCostType
Cost by which elements in a heap can be ordered.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
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:63
#define GNUNET_HELLO_address_free(addr)
Free an address.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:99
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:112
@ GNUNET_HELLO_ADDRESS_INFO_NONE
No additional information.
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_log(kind,...)
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
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.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
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).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
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:674
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:572
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
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:366
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:614
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:509
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:688
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:833
enum GNUNET_GenericReturnValue 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:440
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:772
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:950
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:39
@ GNUNET_NT_WAN
Wide area network (i.e.
Definition: gnunet_nt_lib.h:58
@ GNUNET_NT_UNSPECIFIED
Category of last resort.
Definition: gnunet_nt_lib.h:43
@ GNUNET_NT_LAN
Local area network.
Definition: gnunet_nt_lib.h:53
#define GNUNET_MESSAGE_TYPE_FRAGMENT
FRAGMENT of a larger message.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON
Message send by a peer to notify the other to keep the session alive.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK
UDP ACK.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE
Normal UDP message type.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
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.
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:1506
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:752
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1272
@ GNUNET_SCHEDULER_REASON_READ_READY
The reading socket is ready.
enum GNUNET_GenericReturnValue GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:101
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:404
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:86
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
enum GNUNET_GenericReturnValue GNUNET_STRINGS_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:1134
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
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:436
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:405
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:367
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:616
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:484
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
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:450
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:550
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:569
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
void(* GNUNET_TRANSPORT_SessionInfoCallback)(void *cls, struct GNUNET_ATS_Session *session, const struct GNUNET_TRANSPORT_SessionInfo *info)
Function called by the plugin with information about the current sessions managed by the plugin (for ...
void(* GNUNET_TRANSPORT_TransmitContinuation)(void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire)
Function called by the GNUNET_TRANSPORT_TransmitFunction upon "completion".
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_SessionState
Possible states of a session in a plugin.
@ GNUNET_TRANSPORT_SS_INIT
The session was created (first call for each session object).
@ GNUNET_TRANSPORT_SS_DONE
Session is being torn down and about to disappear.
@ GNUNET_TRANSPORT_SS_UP
Session is fully UP.
@ GNUNET_TRANSPORT_SS_UPDATE
This is just an update about the session, the state did not change.
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define PLUGIN_NAME
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...
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 g...
static void fragment_msg_proc(void *cls, const struct GNUNET_MessageHeader *msg)
Process a defragmented message.
#define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
We keep a defragmentation queue per sender address.
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.
static void udp_select_read(struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
Read and process a message from the given socket.
void(* QueueContinuation)(void *cls, struct UDP_MessageWrapper *udpw, int result)
Function called when a message is removed from the transmission queue.
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.
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.
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...
static void session_timeout(void *cls)
Session was idle, so disconnect it.
static void qc_fragment_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We are finished with a fragment in the message 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...
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.
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 void enqueue(struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
Enqueue a message for transmission and update statistics.
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 enum GNUNET_NetworkType udp_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
Function obtain the network type for a session.
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 ack_message_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We finished sending an acknowledgement.
static void reschedule_session_timeout(struct GNUNET_ATS_Session *s)
Increment session timeout due to activity.
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.
static void udp_plugin_select_v4(void *cls)
We have been notified that our readset has something to read.
static void udp_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
Disconnect from a remote node.
static void udp_plugin_select_v6(void *cls)
We have been notified that our readset has something to read.
static void free_session(struct GNUNET_ATS_Session *s)
Function to free last resources associated with a session.
static void append_port(void *cls, const char *hostname)
Append our port and forward the result.
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).
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 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 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.
static int disconnect_and_free_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Destroy a session, plugin is being unloaded.
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 qc_message_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We are finished with a message from the message queue.
void * libgnunet_plugin_transport_udp_done(void *cls)
The exported method.
static unsigned int udp_query_keepalive_factor(void *cls)
Function that is called to get the keepalive factor.
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.
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've received a UDP Message.
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.
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.
#define LOG(kind,...)
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 dequeue(struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
Remove the given message from the transmission queue and update all applicable statistics.
static int process_inbound_tokenized_messages(void *cls, const struct GNUNET_MessageHeader *hdr)
Message tokenizer has broken up an incoming message.
static void schedule_select_v6(struct Plugin *plugin)
(re)schedule IPv6-select tasks for this plugin.
static int session_cmp_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Find a session with a matching address.
static int send_session_info_iter(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Return information about the given session to the monitor callback.
static void enqueue_fragment(void *cls, const struct GNUNET_MessageHeader *msg)
Function that is called with messages created by the fragmentation module.
void * libgnunet_plugin_transport_udp_init(void *cls)
The exported method.
static void udp_plugin_setup_monitor(void *cls, GNUNET_TRANSPORT_SessionInfoCallback sic, void *sic_cls)
Begin monitoring sessions of a plugin.
#define UDP_SESSION_TIME_OUT
After how much inactivity should a UDP session time out?
static void ack_proc(void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
Transmit an acknowledgement.
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.
#define UDP_MAX_MESSAGES_IN_DEFRAG
Number of messages we can defragment in parallel.
static void schedule_select_v4(struct Plugin *plugin)
(re)schedule IPv4-select tasks for this plugin.
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.
Implementation of the UDP transport protocol.
void stop_broadcast(struct Plugin *plugin)
Stop broadcasting subsystem.
void setup_broadcast(struct Plugin *plugin, struct sockaddr_in6 *server_addrv6, struct sockaddr_in *server_addrv4)
Setup broadcasting subsystem.
#define UDP_MTU
MTU for fragmentation subsystem.
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 struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:431
static struct GNUNET_TIME_Relative interval
Definition: speedup.c:34
Data structure to track defragmentation contexts based on the source of the UDP traffic.
struct GNUNET_DEFRAGMENT_Context * defrag
Defragmentation context.
enum GNUNET_NetworkType network_type
Network type the address belongs to.
struct GNUNET_PeerIdentity sender
Who's message(s) are we defragmenting here? Only initialized once we succeeded and have_sender is set...
int have_sender
Has the sender field been initialized yet?
const union UdpAddress * udp_addr
Source address this receive context is for (allocated at the end of the struct).
struct GNUNET_CONTAINER_HeapNode * hnode
Node in the defrag heap.
struct Plugin * plugin
Reference to master plugin struct.
size_t udp_addr_len
Length of udp_addr.
Closure for find_receive_context().
struct DefragContext * rc
Where to store the result.
size_t udp_addr_len
Number of bytes in udp_addr.
const union UdpAddress * udp_addr
Address to find.
struct GNUNET_ATS_Session * session
Session associated with this context.
Closure for session_cmp_it().
const struct GNUNET_HELLO_Address * address
Address we are looking for.
struct GNUNET_ATS_Session * res
Set to session matching the address.
Session handle for connections.
struct GNUNET_PeerIdentity target
To whom are we talking to.
struct Plugin * plugin
Pointer to the global plugin struct.
unsigned int msgs_in_queue
Number of messages waiting for transmission to this peer.
int in_destroy
Is this session about to be destroyed (sometimes we cannot destroy a session immediately as below us ...
unsigned int rc
Reference counter to indicate that this session is currently being used and must not be destroyed; se...
struct GNUNET_TIME_Absolute timeout
When does this session time out.
struct GNUNET_TIME_Relative flow_delay_from_other_peer
Desired delay for transmissions we received from other peer.
struct GNUNET_HELLO_Address * address
Address.
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer for inbound messages.
struct GNUNET_TIME_Absolute last_transmit_time
What time did we last transmit?
struct UDP_FragmentationContext * frag_ctx
Context for dealing with fragments.
enum GNUNET_NetworkType scope
ATS network type.
unsigned long long bytes_in_queue
Number of bytes waiting for transmission to this peer.
struct GNUNET_TIME_Relative last_expected_msg_delay
desired delay between UDP messages
struct GNUNET_TIME_Relative last_expected_ack_delay
expected delay for ACKs
struct GNUNET_SCHEDULER_Task * timeout_task
Session timeout task.
struct GNUNET_TIME_Relative flow_delay_for_other_peer
Desired delay for next sending we send to other peer.
void * cls
Closure for all of the callbacks.
Defragmentation context (one per connection).
Fragmentation context.
Definition: fragmentation.c:41
An address for communicating with a peer.
size_t address_length
Number of bytes in address.
const void * address
Binary representation of the address (plugin-specific).
Header for all communications.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Handle to a message stream tokenizer.
Definition: mst.c:45
handle to a socket
Definition: network.c:54
The identity of the host (wraps the signing key of the peer).
Handle to a request given to the resolver.
Definition: resolver_api.c:104
Context information passed to each scheduler task.
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 ...
enum GNUNET_SCHEDULER_Reason reason
Reason why the task is run now.
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
The transport service will pass a pointer to a struct of this type as the first and only argument to ...
void * cls
Closure for the various callbacks.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
void * cls
Closure for all of the callbacks.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
GNUNET_TRANSPORT_SessionMonitorSetup setup_monitor
Function to monitor the sessions managed by the plugin.
GNUNET_TRANSPORT_DisconnectPeerFunction disconnect_peer
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
GNUNET_TRANSPORT_GetNetworkTypeForAddress get_network_for_address
Function to obtain the network type for an address.
GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
GNUNET_TRANSPORT_QueryKeepaliveFactorFunction query_keepalive_factor
Function that is used to query keepalive factor.
GNUNET_TRANSPORT_AddressPrettyPrinter address_pretty_printer
Function to pretty-print addresses.
GNUNET_TRANSPORT_AddressToString address_to_string
Function that will be called to convert a binary address to a string (numeric conversion only).
GNUNET_TRANSPORT_GetNetworkType get_network
Function to obtain the network type for a session.
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
GNUNET_TRANSPORT_CheckAddress check_address
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
GNUNET_TRANSPORT_StringToAddress string_to_address
Function that will be called to convert a string address to binary (numeric conversion only).
GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout
Function that will be called whenever the transport service wants to notify the plugin that a session...
Information about a plugin's session.
Network format for IPv4 addresses.
uint16_t u4_port
Port number, in network byte order.
uint32_t ipv4_addr
IPv4 address, in network byte order.
uint32_t options
Optional options and flags for this address.
Network format for IPv6 addresses.
uint32_t options
Optional options and flags for this address.
uint16_t u6_port
Port number, in network byte order.
struct in6_addr ipv6_addr
IPv6 address.
Handle for a plugin.
Definition: block.c:38
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
void * sic_cls
Closure for sic.
char * bind6_address
Address we were told to bind to exclusively (IPv6).
int enable_broadcasting
Is broadcasting enabled: GNUNET_YES or GNUNET_NO.
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.
uint16_t aport
Port we advertise on.
char * bind4_address
Address we were told to bind to exclusively (IPv4).
Closure for append_port().
struct GNUNET_RESOLVER_RequestHandle * resolver_handle
Resolver handle.
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task.
uint16_t port
Port to add after the IP address.
void * asc_cls
Clsoure for asc.
GNUNET_TRANSPORT_AddressStringCallback asc
Function to call with the result.
uint32_t options
Address options.
struct PrettyPrinterContext * prev
DLL.
struct PrettyPrinterContext * next
DLL.
UDP Message-Packet header (after defragmentation).
uint32_t reserved
Always zero for now.
struct GNUNET_MessageHeader header
Message header.
struct GNUNET_PeerIdentity sender
What is the identity of the sender.
UDP ACK Message-Packet header.
uint32_t delay
Desired delay for flow control, in us (in NBO).
struct GNUNET_PeerIdentity sender
What is the identity of the sender.
struct GNUNET_MessageHeader header
Message header.
Context to send fragmented messages.
struct GNUNET_TIME_Absolute next_frag_time
Transmission time for the next fragment.
struct UDP_FragmentationContext * next
Next in linked list.
GNUNET_TRANSPORT_TransmitContinuation cont
Function to call upon completion of the transmission.
struct UDP_FragmentationContext * prev
Previous in linked list.
struct GNUNET_TIME_Absolute start_time
Start time.
struct GNUNET_TIME_Relative flow_delay_from_other_peer
Desired delay for transmissions we received from other peer.
struct Plugin * plugin
The plugin.
size_t payload_size
Payload size of original unfragmented message.
void * cont_cls
Closure for cont.
struct GNUNET_FRAGMENT_Context * frag
Handle for fragmentation.
struct GNUNET_ATS_Session * session
The session this fragmentation context belongs to.
struct GNUNET_TIME_Absolute timeout
Message timeout.
size_t on_wire_size
Bytes used to send all fragments on wire including UDP overhead.
Information we track for each message in the queue.
char * msg_buf
Message with msg_size bytes including UDP-specific overhead.
QueueContinuation qc
Function to call once the message wrapper is being removed from the queue (with success or failure).
struct GNUNET_ATS_Session * session
Session this message belongs to.
void * cont_cls
Closure for cont.
size_t payload_size
Payload size of original message.
struct GNUNET_TIME_Absolute start_time
Message enqueue time.
struct UDP_FragmentationContext * frag_ctx
Fragmentation context.
struct UDP_MessageWrapper * next
DLL of messages, next element.
struct GNUNET_TIME_Absolute timeout
Message timeout.
GNUNET_TRANSPORT_TransmitContinuation cont
External continuation to call upon completion of the transmission, NULL if this queue entry is not fo...
struct UDP_MessageWrapper * prev
DLL of messages, previous element.
size_t msg_size
Size of UDP message to send, including UDP-specific overhead.
void * qc_cls
Closure for qc.
struct GNUNET_TIME_Absolute transmission_time
Desired transmission time for this message, based on the flow limiting information we got from the ot...
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
common internal definitions for transport service
Either an IPv4 or IPv6 UDP address.
struct IPv4UdpAddress v4
IPv4 case.
struct IPv6UdpAddress v6
IPv6 case.