GNUnet  0.10.x
plugin_transport_udp.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2010-2017 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
28 #include "platform.h"
29 #include "plugin_transport_udp.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_util_lib.h"
33 #include "gnunet_nat_service.h"
34 #include "gnunet_protocols.h"
36 #include "gnunet_signatures.h"
37 #include "gnunet_constants.h"
41 #include "transport.h"
42 
43 #define LOG(kind, ...) GNUNET_log_from(kind, "transport-udp", __VA_ARGS__)
44 
48 #define UDP_SESSION_TIME_OUT \
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 {
79 
83  uint32_t reserved;
84 
89 };
90 
91 
95 struct PrettyPrinterContext {
99  struct PrettyPrinterContext *next;
100 
104  struct PrettyPrinterContext *prev;
105 
109  struct Plugin *plugin;
110 
114  struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
115 
120 
124  void *asc_cls;
125 
130 
134  int ipv6;
135 
139  uint32_t options;
140 
144  uint16_t port;
145 };
146 
147 
151 struct GNUNET_ATS_Session {
155  struct GNUNET_PeerIdentity target;
156 
161 
165  struct Plugin *plugin;
166 
171 
175  struct GNUNET_TIME_Relative flow_delay_for_other_peer;
176 
182  struct GNUNET_TIME_Relative flow_delay_from_other_peer;
183 
188 
193 
197  struct GNUNET_TIME_Absolute last_transmit_time;
198 
202  struct GNUNET_TIME_Relative last_expected_ack_delay;
203 
207  struct GNUNET_TIME_Relative last_expected_msg_delay;
208 
213 
217  unsigned long long bytes_in_queue;
218 
222  unsigned int msgs_in_queue;
223 
230  unsigned int rc;
231 
236 
244 };
245 
246 
256 
260  struct Plugin *plugin;
261 
266 
271  const union UdpAddress *udp_addr;
272 
278  struct GNUNET_PeerIdentity sender;
279 
283  size_t udp_addr_len;
284 
288  enum GNUNET_NetworkType network_type;
289 
294 };
295 
296 
305 
310 
314  struct Plugin *plugin;
315 
320 
325 
330 
334  void *cont_cls;
335 
340 
346  struct GNUNET_TIME_Absolute next_frag_time;
347 
353  struct GNUNET_TIME_Relative flow_delay_from_other_peer;
354 
359 
363  size_t payload_size;
364 
368  size_t on_wire_size;
369 };
370 
371 
382 typedef void (*QueueContinuation) (void *cls,
383  struct UDP_MessageWrapper *udpw,
384  int result);
385 
386 
395 
400 
405 
409  char *msg_buf;
410 
416 
420  void *qc_cls;
421 
428 
432  void *cont_cls;
433 
440 
445 
450  struct GNUNET_TIME_Absolute transmission_time;
451 
456 
460  size_t msg_size;
461 
465  size_t payload_size;
466 };
467 
468 
470 
479 
486 
490  struct GNUNET_PeerIdentity sender;
491 };
492 
494 
495 
496 /* ************************* Monitoring *********** */
497 
498 
507 static void
509  struct GNUNET_ATS_Session *session,
511 {
512  struct GNUNET_TRANSPORT_SessionInfo info;
513 
514  if (NULL == plugin->sic)
515  return;
516  if (GNUNET_YES == session->in_destroy)
517  return; /* already destroyed, just RC>0 left-over actions */
518  memset(&info, 0, sizeof(info));
519  info.state = state;
520  info.is_inbound = GNUNET_SYSERR; /* hard to say */
521  info.num_msg_pending = session->msgs_in_queue;
522  info.num_bytes_pending = session->bytes_in_queue;
523  /* info.receive_delay remains zero as this is not supported by UDP
524  (cannot selectively not receive from 'some' peer while continuing
525  to receive from others) */
526  info.session_timeout = session->timeout;
527  info.address = session->address;
528  plugin->sic(plugin->sic_cls, session, &info);
529 }
530 
531 
540 static int
542  const struct GNUNET_PeerIdentity *peer,
543  void *value)
544 {
545  struct Plugin *plugin = cls;
546  struct GNUNET_ATS_Session *session = value;
547 
550  return GNUNET_OK;
551 }
552 
553 
566 static void
569  void *sic_cls)
570 {
571  struct Plugin *plugin = cls;
572 
573  plugin->sic = sic;
574  plugin->sic_cls = sic_cls;
575  if (NULL != sic)
576  {
579  plugin);
580  /* signal end of first iteration */
581  sic(sic_cls, NULL, NULL);
582  }
583 }
584 
585 
586 /* ****************** Little Helpers ****************** */
587 
588 
594 static void
596 {
597  if (NULL != s->address)
598  {
600  s->address = NULL;
601  }
602  if (NULL != s->frag_ctx)
603  {
605  GNUNET_free(s->frag_ctx);
606  s->frag_ctx = NULL;
607  }
608  if (NULL != s->mst)
609  {
611  s->mst = NULL;
612  }
613  GNUNET_free(s);
614 }
615 
616 
625 static unsigned int
627 {
628  return 15;
629 }
630 
631 
639 static enum GNUNET_NetworkType
640 udp_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
641 {
642  return session->scope;
643 }
644 
645 
653 static enum GNUNET_NetworkType
655  const struct GNUNET_HELLO_Address *address)
656 {
657  struct Plugin *plugin = cls;
658  size_t addrlen;
659  struct sockaddr_in a4;
660  struct sockaddr_in6 a6;
661  const struct IPv4UdpAddress *u4;
662  const struct IPv6UdpAddress *u6;
663  const void *sb;
664  size_t sbs;
665 
666  addrlen = address->address_length;
667  if (addrlen == sizeof(struct IPv6UdpAddress))
668  {
669  GNUNET_assert(NULL != address->address); /* make static analysis happy */
670  u6 = address->address;
671  memset(&a6, 0, sizeof(a6));
672 #if HAVE_SOCKADDR_IN_SIN_LEN
673  a6.sin6_len = sizeof(a6);
674 #endif
675  a6.sin6_family = AF_INET6;
676  a6.sin6_port = u6->u6_port;
677  GNUNET_memcpy(&a6.sin6_addr, &u6->ipv6_addr, sizeof(struct in6_addr));
678  sb = &a6;
679  sbs = sizeof(a6);
680  }
681  else if (addrlen == sizeof(struct IPv4UdpAddress))
682  {
683  GNUNET_assert(NULL != address->address); /* make static analysis happy */
684  u4 = address->address;
685  memset(&a4, 0, sizeof(a4));
686 #if HAVE_SOCKADDR_IN_SIN_LEN
687  a4.sin_len = sizeof(a4);
688 #endif
689  a4.sin_family = AF_INET;
690  a4.sin_port = u4->u4_port;
691  a4.sin_addr.s_addr = u4->ipv4_addr;
692  sb = &a4;
693  sbs = sizeof(a4);
694  }
695  else
696  {
697  GNUNET_break(0);
698  return GNUNET_NT_UNSPECIFIED;
699  }
700  return plugin->env->get_address_type(plugin->env->cls, sb, sbs);
701 }
702 
703 
704 /* ******************* Event loop ******************** */
705 
713 static void
714 udp_plugin_select_v4(void *cls);
715 
716 
724 static void
725 udp_plugin_select_v6(void *cls);
726 
727 
733 static void
735 {
736  struct GNUNET_TIME_Relative min_delay;
737  struct GNUNET_TIME_Relative delay;
738  struct UDP_MessageWrapper *udpw;
739  struct UDP_MessageWrapper *min_udpw;
740 
741  if ((GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4))
742  {
743  /* Find a message ready to send:
744  * Flow delay from other peer is expired or not set (0) */
745  min_delay = GNUNET_TIME_UNIT_FOREVER_REL;
746  min_udpw = NULL;
747  for (udpw = plugin->ipv4_queue_head; NULL != udpw; udpw = udpw->next)
748  {
750  if (delay.rel_value_us < min_delay.rel_value_us)
751  {
752  min_delay = delay;
753  min_udpw = udpw;
754  }
755  }
756  if (NULL != plugin->select_task_v4)
758  if (NULL != min_udpw)
759  {
760  if (min_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
761  {
763  "Calculated flow delay for UDPv4 at %s for %s\n",
765  GNUNET_YES),
766  GNUNET_i2s(&min_udpw->session->target));
767  }
768  else
769  {
771  "Calculated flow delay for UDPv4 at %s for %s\n",
773  GNUNET_YES),
774  GNUNET_i2s(&min_udpw->session->target));
775  }
776  }
777  plugin->select_task_v4 =
779  plugin->sockv4,
781  plugin);
782  }
783 }
784 
785 
791 static void
793 {
794  struct GNUNET_TIME_Relative min_delay;
795  struct GNUNET_TIME_Relative delay;
796  struct UDP_MessageWrapper *udpw;
797  struct UDP_MessageWrapper *min_udpw;
798 
799  if ((GNUNET_YES == plugin->enable_ipv6) && (NULL != plugin->sockv6))
800  {
801  min_delay = GNUNET_TIME_UNIT_FOREVER_REL;
802  min_udpw = NULL;
803  for (udpw = plugin->ipv6_queue_head; NULL != udpw; udpw = udpw->next)
804  {
806  if (delay.rel_value_us < min_delay.rel_value_us)
807  {
808  min_delay = delay;
809  min_udpw = udpw;
810  }
811  }
812  if (NULL != plugin->select_task_v6)
814  if (NULL != min_udpw)
815  {
816  if (min_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
817  {
819  "Calculated flow delay for UDPv6 at %s for %s\n",
821  GNUNET_YES),
822  GNUNET_i2s(&min_udpw->session->target));
823  }
824  else
825  {
827  "Calculated flow delay for UDPv6 at %s for %s\n",
829  GNUNET_YES),
830  GNUNET_i2s(&min_udpw->session->target));
831  }
832  }
833  plugin->select_task_v6 =
835  plugin->sockv6,
837  plugin);
838  }
839 }
840 
841 
842 /* ******************* Address to string and back ***************** */
843 
844 
856 const char *
857 udp_address_to_string(void *cls, const void *addr, size_t addrlen)
858 {
859  static char rbuf[INET6_ADDRSTRLEN + 10];
860  char buf[INET6_ADDRSTRLEN];
861  const void *sb;
862  struct in_addr a4;
863  struct in6_addr a6;
864  const struct IPv4UdpAddress *t4;
865  const struct IPv6UdpAddress *t6;
866  int af;
867  uint16_t port;
868  uint32_t options;
869 
870  if (NULL == addr)
871  {
872  GNUNET_break_op(0);
873  return NULL;
874  }
875 
876  if (addrlen == sizeof(struct IPv6UdpAddress))
877  {
878  t6 = addr;
879  af = AF_INET6;
880  options = ntohl(t6->options);
881  port = ntohs(t6->u6_port);
882  a6 = t6->ipv6_addr;
883  sb = &a6;
884  }
885  else if (addrlen == sizeof(struct IPv4UdpAddress))
886  {
887  t4 = addr;
888  af = AF_INET;
889  options = ntohl(t4->options);
890  port = ntohs(t4->u4_port);
891  a4.s_addr = t4->ipv4_addr;
892  sb = &a4;
893  }
894  else
895  {
896  GNUNET_break_op(0);
897  return NULL;
898  }
899  inet_ntop(af, sb, buf, INET6_ADDRSTRLEN);
900  GNUNET_snprintf(rbuf,
901  sizeof(rbuf),
902  (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u",
903  PLUGIN_NAME,
904  options,
905  buf,
906  port);
907  return rbuf;
908 }
909 
910 
922 static int
924  const char *addr,
925  uint16_t addrlen,
926  void **buf,
927  size_t *added)
928 {
929  struct sockaddr_storage socket_address;
930  char *address;
931  char *plugin;
932  char *optionstr;
933  uint32_t options;
934 
935  /* Format tcp.options.address:port */
936  address = NULL;
937  plugin = NULL;
938  optionstr = NULL;
939 
940  if ((NULL == addr) || (0 == addrlen))
941  {
942  GNUNET_break(0);
943  return GNUNET_SYSERR;
944  }
945  if ('\0' != addr[addrlen - 1])
946  {
947  GNUNET_break(0);
948  return GNUNET_SYSERR;
949  }
950  if (strlen(addr) != addrlen - 1)
951  {
952  GNUNET_break(0);
953  return GNUNET_SYSERR;
954  }
955  plugin = GNUNET_strdup(addr);
956  optionstr = strchr(plugin, '.');
957  if (NULL == optionstr)
958  {
959  GNUNET_break(0);
960  GNUNET_free(plugin);
961  return GNUNET_SYSERR;
962  }
963  optionstr[0] = '\0';
964  optionstr++;
965  options = atol(optionstr);
966  address = strchr(optionstr, '.');
967  if (NULL == address)
968  {
969  GNUNET_break(0);
970  GNUNET_free(plugin);
971  return GNUNET_SYSERR;
972  }
973  address[0] = '\0';
974  address++;
975 
976  if (GNUNET_OK !=
977  GNUNET_STRINGS_to_address_ip(address, strlen(address), &socket_address))
978  {
979  GNUNET_break(0);
980  GNUNET_free(plugin);
981  return GNUNET_SYSERR;
982  }
983  GNUNET_free(plugin);
984 
985  switch (socket_address.ss_family)
986  {
987  case AF_INET: {
988  struct IPv4UdpAddress *u4;
989  const struct sockaddr_in *in4 =
990  (const struct sockaddr_in *)&socket_address;
991 
992  u4 = GNUNET_new(struct IPv4UdpAddress);
993  u4->options = htonl(options);
994  u4->ipv4_addr = in4->sin_addr.s_addr;
995  u4->u4_port = in4->sin_port;
996  *buf = u4;
997  *added = sizeof(struct IPv4UdpAddress);
998  return GNUNET_OK;
999  }
1000 
1001  case AF_INET6: {
1002  struct IPv6UdpAddress *u6;
1003  const struct sockaddr_in6 *in6 =
1004  (const struct sockaddr_in6 *)&socket_address;
1005 
1006  u6 = GNUNET_new(struct IPv6UdpAddress);
1007  u6->options = htonl(options);
1008  u6->ipv6_addr = in6->sin6_addr;
1009  u6->u6_port = in6->sin6_port;
1010  *buf = u6;
1011  *added = sizeof(struct IPv6UdpAddress);
1012  return GNUNET_OK;
1013  }
1014 
1015  default:
1016  GNUNET_break(0);
1017  return GNUNET_SYSERR;
1018  }
1019 }
1020 
1021 
1028 static void
1029 append_port(void *cls, const char *hostname)
1030 {
1031  struct PrettyPrinterContext *ppc = cls;
1032  struct Plugin *plugin = ppc->plugin;
1033  char *ret;
1034 
1035  if (NULL == hostname)
1036  {
1037  /* Final call, done */
1039  plugin->ppc_dll_tail,
1040  ppc);
1041  ppc->resolver_handle = NULL;
1042  ppc->asc(ppc->asc_cls, NULL, GNUNET_OK);
1043  GNUNET_free(ppc);
1044  return;
1045  }
1046  if (GNUNET_YES == ppc->ipv6)
1047  GNUNET_asprintf(&ret,
1048  "%s.%u.[%s]:%d",
1049  PLUGIN_NAME,
1050  ppc->options,
1051  hostname,
1052  ppc->port);
1053  else
1054  GNUNET_asprintf(&ret,
1055  "%s.%u.%s:%d",
1056  PLUGIN_NAME,
1057  ppc->options,
1058  hostname,
1059  ppc->port);
1060  ppc->asc(ppc->asc_cls, ret, GNUNET_OK);
1061  GNUNET_free(ret);
1062 }
1063 
1064 
1079 static void
1081  const char *type,
1082  const void *addr,
1083  size_t addrlen,
1084  int numeric,
1087  void *asc_cls)
1088 {
1089  struct Plugin *plugin = cls;
1090  struct PrettyPrinterContext *ppc;
1091  const struct sockaddr *sb;
1092  size_t sbs;
1093  struct sockaddr_in a4;
1094  struct sockaddr_in6 a6;
1095  const struct IPv4UdpAddress *u4;
1096  const struct IPv6UdpAddress *u6;
1097  uint16_t port;
1098  uint32_t options;
1099 
1100  if (addrlen == sizeof(struct IPv6UdpAddress))
1101  {
1102  u6 = addr;
1103  memset(&a6, 0, sizeof(a6));
1104  a6.sin6_family = AF_INET6;
1105 #if HAVE_SOCKADDR_IN_SIN_LEN
1106  a6.sin6_len = sizeof(a6);
1107 #endif
1108  a6.sin6_port = u6->u6_port;
1109  a6.sin6_addr = u6->ipv6_addr;
1110  port = ntohs(u6->u6_port);
1111  options = ntohl(u6->options);
1112  sb = (const struct sockaddr *)&a6;
1113  sbs = sizeof(a6);
1114  }
1115  else if (addrlen == sizeof(struct IPv4UdpAddress))
1116  {
1117  u4 = addr;
1118  memset(&a4, 0, sizeof(a4));
1119  a4.sin_family = AF_INET;
1120 #if HAVE_SOCKADDR_IN_SIN_LEN
1121  a4.sin_len = sizeof(a4);
1122 #endif
1123  a4.sin_port = u4->u4_port;
1124  a4.sin_addr.s_addr = u4->ipv4_addr;
1125  port = ntohs(u4->u4_port);
1126  options = ntohl(u4->options);
1127  sb = (const struct sockaddr *)&a4;
1128  sbs = sizeof(a4);
1129  }
1130  else
1131  {
1132  /* invalid address */
1133  GNUNET_break_op(0);
1134  asc(asc_cls, NULL, GNUNET_SYSERR);
1135  asc(asc_cls, NULL, GNUNET_OK);
1136  return;
1137  }
1138  ppc = GNUNET_new(struct PrettyPrinterContext);
1139  ppc->plugin = plugin;
1140  ppc->asc = asc;
1141  ppc->asc_cls = asc_cls;
1142  ppc->port = port;
1143  ppc->options = options;
1144  if (addrlen == sizeof(struct IPv6UdpAddress))
1145  ppc->ipv6 = GNUNET_YES;
1146  else
1147  ppc->ipv6 = GNUNET_NO;
1148  GNUNET_CONTAINER_DLL_insert(plugin->ppc_dll_head, plugin->ppc_dll_tail, ppc);
1150  sbs,
1151  !numeric,
1152  timeout,
1153  &append_port,
1154  ppc);
1155 }
1156 
1157 
1167 static int
1168 check_port(const struct Plugin *plugin, uint16_t in_port)
1169 {
1170  if ((plugin->port == in_port) || (plugin->aport == in_port))
1171  return GNUNET_OK;
1172  return GNUNET_SYSERR;
1173 }
1174 
1175 
1191 static int
1192 udp_plugin_check_address(void *cls, const void *addr, size_t addrlen)
1193 {
1194  struct Plugin *plugin = cls;
1195  const struct IPv4UdpAddress *v4;
1196  const struct IPv6UdpAddress *v6;
1197 
1198  if (sizeof(struct IPv4UdpAddress) == addrlen)
1199  {
1200  struct sockaddr_in s4;
1201 
1202  v4 = (const struct IPv4UdpAddress *)addr;
1203  if (GNUNET_OK != check_port(plugin, ntohs(v4->u4_port)))
1204  return GNUNET_SYSERR;
1205  memset(&s4, 0, sizeof(s4));
1206  s4.sin_family = AF_INET;
1207 #if HAVE_SOCKADDR_IN_SIN_LEN
1208  s4.sin_len = sizeof(s4);
1209 #endif
1210  s4.sin_port = v4->u4_port;
1211  s4.sin_addr.s_addr = v4->ipv4_addr;
1212 
1213  if (GNUNET_OK !=
1214  GNUNET_NAT_test_address(plugin->nat, &s4, sizeof(struct sockaddr_in)))
1215  return GNUNET_SYSERR;
1216  }
1217  else if (sizeof(struct IPv6UdpAddress) == addrlen)
1218  {
1219  struct sockaddr_in6 s6;
1220 
1221  v6 = (const struct IPv6UdpAddress *)addr;
1222  if (IN6_IS_ADDR_LINKLOCAL(&v6->ipv6_addr))
1223  return GNUNET_OK; /* plausible, if unlikely... */
1224  memset(&s6, 0, sizeof(s6));
1225  s6.sin6_family = AF_INET6;
1226 #if HAVE_SOCKADDR_IN_SIN_LEN
1227  s6.sin6_len = sizeof(s6);
1228 #endif
1229  s6.sin6_port = v6->u6_port;
1230  s6.sin6_addr = v6->ipv6_addr;
1231 
1232  if (GNUNET_OK != GNUNET_NAT_test_address(plugin->nat,
1233  &s6,
1234  sizeof(struct sockaddr_in6)))
1235  return GNUNET_SYSERR;
1236  }
1237  else
1238  {
1239  GNUNET_break_op(0);
1240  return GNUNET_SYSERR;
1241  }
1242  return GNUNET_OK;
1243 }
1244 
1245 
1258 static void
1260  void **app_ctx,
1261  int add_remove,
1263  const struct sockaddr *addr,
1264  socklen_t addrlen)
1265 {
1266  struct Plugin *plugin = cls;
1267  struct GNUNET_HELLO_Address *address;
1268  struct IPv4UdpAddress u4;
1269  struct IPv6UdpAddress u6;
1270  void *arg;
1271  size_t args;
1272 
1273  (void)app_ctx;
1275  (GNUNET_YES == add_remove) ? "NAT notification to add address `%s'\n"
1276  : "NAT notification to remove address `%s'\n",
1277  GNUNET_a2s(addr, addrlen));
1278  /* convert 'address' to our internal format */
1279  switch (addr->sa_family)
1280  {
1281  case AF_INET: {
1282  const struct sockaddr_in *i4;
1283 
1284  GNUNET_assert(sizeof(struct sockaddr_in) == addrlen);
1285  i4 = (const struct sockaddr_in *)addr;
1286  if (0 == ntohs(i4->sin_port))
1287  return; /* Port = 0 means unmapped, ignore these for UDP. */
1288  memset(&u4, 0, sizeof(u4));
1289  u4.options = htonl(plugin->myoptions);
1290  u4.ipv4_addr = i4->sin_addr.s_addr;
1291  u4.u4_port = i4->sin_port;
1292  arg = &u4;
1293  args = sizeof(struct IPv4UdpAddress);
1294  break;
1295  }
1296 
1297  case AF_INET6: {
1298  const struct sockaddr_in6 *i6;
1299 
1300  GNUNET_assert(sizeof(struct sockaddr_in6) == addrlen);
1301  i6 = (const struct sockaddr_in6 *)addr;
1302  if (0 == ntohs(i6->sin6_port))
1303  return; /* Port = 0 means unmapped, ignore these for UDP. */
1304  memset(&u6, 0, sizeof(u6));
1305  u6.options = htonl(plugin->myoptions);
1306  u6.ipv6_addr = i6->sin6_addr;
1307  u6.u6_port = i6->sin6_port;
1308  arg = &u6;
1309  args = sizeof(struct IPv6UdpAddress);
1310  break;
1311  }
1312 
1313  default:
1314  GNUNET_break(0);
1315  return;
1316  }
1317  /* modify our published address list */
1318  /* TODO: use 'ac' here in the future... */
1319  address = GNUNET_HELLO_address_allocate(plugin->env->my_identity,
1320  PLUGIN_NAME,
1321  arg,
1322  args,
1324  plugin->env->notify_address(plugin->env->cls, add_remove, address);
1325  GNUNET_HELLO_address_free(address);
1326 }
1327 
1328 
1329 /* ********************* Finding sessions ******************* */
1330 
1331 
1340 
1345 };
1346 
1347 
1356 static int
1357 session_cmp_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
1358 {
1359  struct GNUNET_ATS_SessionCompareContext *cctx = cls;
1360  struct GNUNET_ATS_Session *s = value;
1361 
1362  if (0 == GNUNET_HELLO_address_cmp(s->address, cctx->address))
1363  {
1365  cctx->res = s;
1366  return GNUNET_NO;
1367  }
1368  return GNUNET_OK;
1369 }
1370 
1371 
1381 static struct GNUNET_ATS_Session *
1383  const struct GNUNET_HELLO_Address *address)
1384 {
1385  struct Plugin *plugin = cls;
1386  const struct IPv6UdpAddress *udp_a6;
1387  const struct IPv4UdpAddress *udp_a4;
1389 
1390  if (NULL == address->address)
1391  {
1392  GNUNET_break(0);
1393  return NULL;
1394  }
1395  if (sizeof(struct IPv4UdpAddress) == address->address_length)
1396  {
1397  if (NULL == plugin->sockv4)
1398  return NULL;
1399  udp_a4 = (const struct IPv4UdpAddress *)address->address;
1400  if (0 == udp_a4->u4_port)
1401  {
1402  GNUNET_break(0);
1403  return NULL;
1404  }
1405  }
1406  else if (sizeof(struct IPv6UdpAddress) == address->address_length)
1407  {
1408  if (NULL == plugin->sockv6)
1409  return NULL;
1410  udp_a6 = (const struct IPv6UdpAddress *)address->address;
1411  if (0 == udp_a6->u6_port)
1412  {
1413  GNUNET_break(0);
1414  return NULL;
1415  }
1416  }
1417  else
1418  {
1419  GNUNET_break(0);
1420  return NULL;
1421  }
1422 
1423  /* check if session already exists */
1424  cctx.address = address;
1425  cctx.res = NULL;
1427  "Looking for existing session for peer `%s' with address `%s'\n",
1428  GNUNET_i2s(&address->peer),
1429  udp_address_to_string(plugin,
1430  address->address,
1431  address->address_length));
1433  &address->peer,
1434  &session_cmp_it,
1435  &cctx);
1436  if (NULL == cctx.res)
1437  return NULL;
1438  LOG(GNUNET_ERROR_TYPE_DEBUG, "Found existing session %p\n", cctx.res);
1439  return cctx.res;
1440 }
1441 
1442 
1443 /* ********************** Timeout ****************** */
1444 
1445 
1451 static void
1453 {
1454  if (GNUNET_YES == s->in_destroy)
1455  return;
1456  GNUNET_assert(NULL != s->timeout_task);
1458 }
1459 
1460 
1470 static void
1472  const struct GNUNET_PeerIdentity *peer,
1473  struct GNUNET_ATS_Session *session)
1474 {
1475  struct Plugin *plugin = cls;
1476 
1477  if (GNUNET_YES !=
1479  peer,
1480  session))
1481  {
1482  GNUNET_break(0);
1483  return;
1484  }
1485  /* Reschedule session timeout */
1486  reschedule_session_timeout(session);
1487 }
1488 
1489 
1490 /* ************************* Sending ************************ */
1491 
1492 
1500 static void
1501 dequeue(struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
1502 {
1503  struct GNUNET_ATS_Session *session = udpw->session;
1504 
1505  if (plugin->bytes_in_buffer < udpw->msg_size)
1506  {
1507  GNUNET_break(0);
1508  }
1509  else
1510  {
1511  GNUNET_STATISTICS_update(plugin->env->stats,
1512  "# UDP, total bytes in send buffers",
1513  -(long long)udpw->msg_size,
1514  GNUNET_NO);
1515  plugin->bytes_in_buffer -= udpw->msg_size;
1516  }
1517  GNUNET_STATISTICS_update(plugin->env->stats,
1518  "# UDP, total messages in send buffers",
1519  -1,
1520  GNUNET_NO);
1521  if (sizeof(struct IPv4UdpAddress) == udpw->session->address->address_length)
1522  {
1524  plugin->ipv4_queue_tail,
1525  udpw);
1526  }
1527  else if (sizeof(struct IPv6UdpAddress) ==
1528  udpw->session->address->address_length)
1529  {
1531  plugin->ipv6_queue_tail,
1532  udpw);
1533  }
1534  else
1535  {
1536  GNUNET_break(0);
1537  return;
1538  }
1539  GNUNET_assert(session->msgs_in_queue > 0);
1540  session->msgs_in_queue--;
1541  GNUNET_assert(session->bytes_in_queue >= udpw->msg_size);
1542  session->bytes_in_queue -= udpw->msg_size;
1543 }
1544 
1545 
1552 static void
1553 enqueue(struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
1554 {
1555  struct GNUNET_ATS_Session *session = udpw->session;
1556 
1557  if (GNUNET_YES == session->in_destroy)
1558  {
1559  GNUNET_break(0);
1560  GNUNET_free(udpw);
1561  return;
1562  }
1563  if (plugin->bytes_in_buffer > INT64_MAX - udpw->msg_size)
1564  {
1565  GNUNET_break(0);
1566  }
1567  else
1568  {
1569  GNUNET_STATISTICS_update(plugin->env->stats,
1570  "# UDP, total bytes in send buffers",
1571  udpw->msg_size,
1572  GNUNET_NO);
1573  plugin->bytes_in_buffer += udpw->msg_size;
1574  }
1575  GNUNET_STATISTICS_update(plugin->env->stats,
1576  "# UDP, total messages in send buffers",
1577  1,
1578  GNUNET_NO);
1579  if (sizeof(struct IPv4UdpAddress) == udpw->session->address->address_length)
1580  {
1582  plugin->ipv4_queue_tail,
1583  udpw);
1584  }
1585  else if (sizeof(struct IPv6UdpAddress) ==
1586  udpw->session->address->address_length)
1587  {
1589  plugin->ipv6_queue_tail,
1590  udpw);
1591  }
1592  else
1593  {
1594  GNUNET_break(0);
1595  udpw->cont(udpw->cont_cls,
1596  &session->target,
1597  GNUNET_SYSERR,
1598  udpw->msg_size,
1599  0);
1600  GNUNET_free(udpw);
1601  return;
1602  }
1603  session->msgs_in_queue++;
1604  session->bytes_in_queue += udpw->msg_size;
1605 }
1606 
1607 
1618 static void
1620 {
1621  struct Plugin *plugin = frag_ctx->plugin;
1622  struct GNUNET_ATS_Session *s = frag_ctx->session;
1623  struct UDP_MessageWrapper *udpw;
1624  struct UDP_MessageWrapper *tmp;
1625  size_t overhead;
1626  struct GNUNET_TIME_Relative delay;
1627 
1629  "%p: Fragmented message removed with result %s\n",
1630  frag_ctx,
1631  (result == GNUNET_SYSERR) ? "FAIL" : "SUCCESS");
1632  /* Call continuation for fragmented message */
1633  if (frag_ctx->on_wire_size >= frag_ctx->payload_size)
1634  overhead = frag_ctx->on_wire_size - frag_ctx->payload_size;
1635  else
1636  overhead = frag_ctx->on_wire_size;
1637  delay = GNUNET_TIME_absolute_get_duration(frag_ctx->start_time);
1638  if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
1639  {
1641  "Fragmented message acknowledged after %s (expected at %s)\n",
1644  }
1645  else
1646  {
1648  "Fragmented message acknowledged after %s (expected at %s)\n",
1651  }
1652 
1653  if (NULL != frag_ctx->cont)
1654  frag_ctx->cont(frag_ctx->cont_cls,
1655  &s->target,
1656  result,
1657  s->frag_ctx->payload_size,
1658  frag_ctx->on_wire_size);
1659  GNUNET_STATISTICS_update(plugin->env->stats,
1660  "# UDP, fragmented messages active",
1661  -1,
1662  GNUNET_NO);
1663 
1664  if (GNUNET_OK == result)
1665  {
1666  GNUNET_STATISTICS_update(plugin->env->stats,
1667  "# UDP, fragmented msgs, messages, sent, success",
1668  1,
1669  GNUNET_NO);
1670  GNUNET_STATISTICS_update(plugin->env->stats,
1671  "# UDP, fragmented msgs, bytes payload, sent, success",
1672  s->frag_ctx->payload_size,
1673  GNUNET_NO);
1675  plugin->env->stats,
1676  "# UDP, fragmented msgs, bytes overhead, sent, success",
1677  overhead,
1678  GNUNET_NO);
1679  GNUNET_STATISTICS_update(plugin->env->stats,
1680  "# UDP, total, bytes overhead, sent",
1681  overhead,
1682  GNUNET_NO);
1683  GNUNET_STATISTICS_update(plugin->env->stats,
1684  "# UDP, total, bytes payload, sent",
1685  s->frag_ctx->payload_size,
1686  GNUNET_NO);
1687  }
1688  else
1689  {
1690  GNUNET_STATISTICS_update(plugin->env->stats,
1691  "# UDP, fragmented msgs, messages, sent, failure",
1692  1,
1693  GNUNET_NO);
1694  GNUNET_STATISTICS_update(plugin->env->stats,
1695  "# UDP, fragmented msgs, bytes payload, sent, failure",
1696  s->frag_ctx->payload_size,
1697  GNUNET_NO);
1698  GNUNET_STATISTICS_update(plugin->env->stats,
1699  "# UDP, fragmented msgs, bytes payload, sent, failure",
1700  overhead,
1701  GNUNET_NO);
1702  GNUNET_STATISTICS_update(plugin->env->stats,
1703  "# UDP, fragmented msgs, bytes payload, sent, failure",
1704  overhead,
1705  GNUNET_NO);
1706  }
1707 
1708  /* Remove remaining fragments from queue, no need to transmit those
1709  any longer. */
1710  if (s->address->address_length == sizeof(struct IPv6UdpAddress))
1711  {
1712  udpw = plugin->ipv6_queue_head;
1713  while (NULL != udpw)
1714  {
1715  tmp = udpw->next;
1716  if ((udpw->frag_ctx != NULL) && (udpw->frag_ctx == frag_ctx))
1717  {
1718  dequeue(plugin, udpw);
1719  GNUNET_free(udpw);
1720  }
1721  udpw = tmp;
1722  }
1723  }
1724  if (s->address->address_length == sizeof(struct IPv4UdpAddress))
1725  {
1726  udpw = plugin->ipv4_queue_head;
1727  while (NULL != udpw)
1728  {
1729  tmp = udpw->next;
1730  if ((NULL != udpw->frag_ctx) && (udpw->frag_ctx == frag_ctx))
1731  {
1732  dequeue(plugin, udpw);
1733  GNUNET_free(udpw);
1734  }
1735  udpw = tmp;
1736  }
1737  }
1742  s->frag_ctx = NULL;
1743  GNUNET_free(frag_ctx);
1744 }
1745 
1746 
1755 static void
1756 qc_fragment_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
1757 {
1758  struct Plugin *plugin = cls;
1759 
1760  GNUNET_assert(NULL != udpw->frag_ctx);
1761  if (GNUNET_OK == result)
1762  {
1764  "Fragment of message with %u bytes transmitted to %s\n",
1765  (unsigned int)udpw->payload_size,
1766  GNUNET_i2s(&udpw->session->target));
1768  GNUNET_STATISTICS_update(plugin->env->stats,
1769  "# UDP, fragmented msgs, fragments, sent, success",
1770  1,
1771  GNUNET_NO);
1773  plugin->env->stats,
1774  "# UDP, fragmented msgs, fragments bytes, sent, success",
1775  udpw->msg_size,
1776  GNUNET_NO);
1777  }
1778  else
1779  {
1781  "Failed to transmit fragment of message with %u bytes to %s\n",
1782  (unsigned int)udpw->payload_size,
1783  GNUNET_i2s(&udpw->session->target));
1785  GNUNET_STATISTICS_update(plugin->env->stats,
1786  "# UDP, fragmented msgs, fragments, sent, failure",
1787  1,
1788  GNUNET_NO);
1790  plugin->env->stats,
1791  "# UDP, fragmented msgs, fragments bytes, sent, failure",
1792  udpw->msg_size,
1793  GNUNET_NO);
1794  }
1795 }
1796 
1797 
1807 static void
1808 enqueue_fragment(void *cls, const struct GNUNET_MessageHeader *msg)
1809 {
1810  struct UDP_FragmentationContext *frag_ctx = cls;
1811  struct Plugin *plugin = frag_ctx->plugin;
1812  struct UDP_MessageWrapper *udpw;
1813  struct GNUNET_ATS_Session *session = frag_ctx->session;
1814  size_t msg_len = ntohs(msg->size);
1815 
1816  LOG(GNUNET_ERROR_TYPE_DEBUG, "Enqueuing fragment with %u bytes\n", msg_len);
1817  udpw = GNUNET_malloc(sizeof(struct UDP_MessageWrapper) + msg_len);
1818  udpw->session = session;
1819  udpw->msg_buf = (char *)&udpw[1];
1820  udpw->msg_size = msg_len;
1821  udpw->payload_size = msg_len; /* FIXME: minus fragment overhead */
1822  udpw->timeout = frag_ctx->timeout;
1823  udpw->start_time = frag_ctx->start_time;
1824  udpw->transmission_time = frag_ctx->next_frag_time;
1825  frag_ctx->next_frag_time =
1827  frag_ctx->flow_delay_from_other_peer);
1828  udpw->frag_ctx = frag_ctx;
1829  udpw->qc = &qc_fragment_sent;
1830  udpw->qc_cls = plugin;
1831  GNUNET_memcpy(udpw->msg_buf, msg, msg_len);
1832  enqueue(plugin, udpw);
1833  if (session->address->address_length == sizeof(struct IPv4UdpAddress))
1834  schedule_select_v4(plugin);
1835  else
1836  schedule_select_v6(plugin);
1837 }
1838 
1839 
1848 static void
1849 qc_message_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
1850 {
1851  struct Plugin *plugin = cls;
1852  size_t overhead;
1853  struct GNUNET_TIME_Relative delay;
1854 
1855  if (udpw->msg_size >= udpw->payload_size)
1856  overhead = udpw->msg_size - udpw->payload_size;
1857  else
1858  overhead = udpw->msg_size;
1859 
1860  if (NULL != udpw->cont)
1861  {
1863  if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
1864  {
1866  "Message sent via UDP with delay of %s\n",
1868  }
1869  else
1870  {
1872  "Message sent via UDP with delay of %s\n",
1874  }
1875  udpw->cont(udpw->cont_cls,
1876  &udpw->session->target,
1877  result,
1878  udpw->payload_size,
1879  overhead);
1880  }
1881  if (GNUNET_OK == result)
1882  {
1883  GNUNET_STATISTICS_update(plugin->env->stats,
1884  "# UDP, unfragmented msgs, messages, sent, success",
1885  1,
1886  GNUNET_NO);
1888  plugin->env->stats,
1889  "# UDP, unfragmented msgs, bytes payload, sent, success",
1890  udpw->payload_size,
1891  GNUNET_NO);
1893  plugin->env->stats,
1894  "# UDP, unfragmented msgs, bytes overhead, sent, success",
1895  overhead,
1896  GNUNET_NO);
1897  GNUNET_STATISTICS_update(plugin->env->stats,
1898  "# UDP, total, bytes overhead, sent",
1899  overhead,
1900  GNUNET_NO);
1901  GNUNET_STATISTICS_update(plugin->env->stats,
1902  "# UDP, total, bytes payload, sent",
1903  udpw->payload_size,
1904  GNUNET_NO);
1905  }
1906  else
1907  {
1908  GNUNET_STATISTICS_update(plugin->env->stats,
1909  "# UDP, unfragmented msgs, messages, sent, failure",
1910  1,
1911  GNUNET_NO);
1913  plugin->env->stats,
1914  "# UDP, unfragmented msgs, bytes payload, sent, failure",
1915  udpw->payload_size,
1916  GNUNET_NO);
1918  plugin->env->stats,
1919  "# UDP, unfragmented msgs, bytes overhead, sent, failure",
1920  overhead,
1921  GNUNET_NO);
1922  }
1923 }
1924 
1925 
1953 static ssize_t
1955  struct GNUNET_ATS_Session *s,
1956  const char *msgbuf,
1957  size_t msgbuf_size,
1958  unsigned int priority,
1959  struct GNUNET_TIME_Relative to,
1961  void *cont_cls)
1962 {
1963  struct Plugin *plugin = cls;
1964  size_t udpmlen = msgbuf_size + sizeof(struct UDPMessage);
1965  struct UDP_FragmentationContext *frag_ctx;
1966  struct UDP_MessageWrapper *udpw;
1967  struct UDPMessage *udp;
1968  char mbuf[udpmlen] GNUNET_ALIGN;
1969  struct GNUNET_TIME_Relative latency;
1970 
1971  if ((sizeof(struct IPv6UdpAddress) == s->address->address_length) &&
1972  (NULL == plugin->sockv6))
1973  return GNUNET_SYSERR;
1974  if ((sizeof(struct IPv4UdpAddress) == s->address->address_length) &&
1975  (NULL == plugin->sockv4))
1976  return GNUNET_SYSERR;
1977  if (udpmlen >= GNUNET_MAX_MESSAGE_SIZE)
1978  {
1979  GNUNET_break(0);
1980  return GNUNET_SYSERR;
1981  }
1982  if (GNUNET_YES !=
1984  &s->target,
1985  s))
1986  {
1987  GNUNET_break(0);
1988  return GNUNET_SYSERR;
1989  }
1991  "UDP transmits %u-byte message to `%s' using address `%s'\n",
1992  udpmlen,
1993  GNUNET_i2s(&s->target),
1994  udp_address_to_string(plugin,
1995  s->address->address,
1996  s->address->address_length));
1997 
1998  udp = (struct UDPMessage *)mbuf;
1999  udp->header.size = htons(udpmlen);
2001  udp->reserved = htonl(0);
2002  udp->sender = *plugin->env->my_identity;
2003 
2004  /* We do not update the session time out here! Otherwise this
2005  * session will not timeout since we send keep alive before session
2006  * can timeout.
2007  *
2008  * For UDP we update session timeout only on receive, this will
2009  * cover keep alives, since remote peer will reply with keep alive
2010  * responses!
2011  */
2012  if (udpmlen <= UDP_MTU)
2013  {
2014  /* unfragmented message */
2015  udpw = GNUNET_malloc(sizeof(struct UDP_MessageWrapper) + udpmlen);
2016  udpw->session = s;
2017  udpw->msg_buf = (char *)&udpw[1];
2018  udpw->msg_size = udpmlen; /* message size with UDP overhead */
2019  udpw->payload_size = msgbuf_size; /* message size without UDP overhead */
2023  s->last_transmit_time =
2026  udpw->cont = cont;
2027  udpw->cont_cls = cont_cls;
2028  udpw->frag_ctx = NULL;
2029  udpw->qc = &qc_message_sent;
2030  udpw->qc_cls = plugin;
2031  GNUNET_memcpy(udpw->msg_buf, udp, sizeof(struct UDPMessage));
2032  GNUNET_memcpy(&udpw->msg_buf[sizeof(struct UDPMessage)],
2033  msgbuf,
2034  msgbuf_size);
2035  enqueue(plugin, udpw);
2036  GNUNET_STATISTICS_update(plugin->env->stats,
2037  "# UDP, unfragmented messages queued total",
2038  1,
2039  GNUNET_NO);
2040  GNUNET_STATISTICS_update(plugin->env->stats,
2041  "# UDP, unfragmented bytes payload queued total",
2042  msgbuf_size,
2043  GNUNET_NO);
2044  if (s->address->address_length == sizeof(struct IPv4UdpAddress))
2045  schedule_select_v4(plugin);
2046  else
2047  schedule_select_v6(plugin);
2048  }
2049  else
2050  {
2051  /* fragmented message */
2052  if (NULL != s->frag_ctx)
2053  return GNUNET_SYSERR;
2054  GNUNET_memcpy(&udp[1], msgbuf, msgbuf_size);
2055  frag_ctx = GNUNET_new(struct UDP_FragmentationContext);
2056  frag_ctx->plugin = plugin;
2057  frag_ctx->session = s;
2058  frag_ctx->cont = cont;
2059  frag_ctx->cont_cls = cont_cls;
2060  frag_ctx->start_time = GNUNET_TIME_absolute_get();
2061  frag_ctx->next_frag_time = s->last_transmit_time;
2062  frag_ctx->flow_delay_from_other_peer =
2064  1 + (msgbuf_size / UDP_MTU));
2065  frag_ctx->timeout = GNUNET_TIME_relative_to_absolute(to);
2066  frag_ctx->payload_size =
2067  msgbuf_size; /* unfragmented message size without UDP overhead */
2068  frag_ctx->on_wire_size = 0; /* bytes with UDP and fragmentation overhead */
2069  frag_ctx->frag = GNUNET_FRAGMENT_context_create(plugin->env->stats,
2070  UDP_MTU,
2071  &plugin->tracker,
2074  &udp->header,
2076  frag_ctx);
2077  s->frag_ctx = frag_ctx;
2078  s->last_transmit_time = frag_ctx->next_frag_time;
2080  if (latency.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
2082  "Enqueued fragments will take %s for transmission to %s (queue size: %u)\n",
2084  GNUNET_i2s(&s->target),
2085  (unsigned int)s->msgs_in_queue);
2086  else
2088  "Enqueued fragments will take %s for transmission to %s (queue size: %u)\n",
2090  GNUNET_i2s(&s->target),
2091  (unsigned int)s->msgs_in_queue);
2092 
2093  GNUNET_STATISTICS_update(plugin->env->stats,
2094  "# UDP, fragmented messages active",
2095  1,
2096  GNUNET_NO);
2097  GNUNET_STATISTICS_update(plugin->env->stats,
2098  "# UDP, fragmented messages, total",
2099  1,
2100  GNUNET_NO);
2101  GNUNET_STATISTICS_update(plugin->env->stats,
2102  "# UDP, fragmented bytes (payload)",
2103  frag_ctx->payload_size,
2104  GNUNET_NO);
2105  }
2107  return udpmlen;
2108 }
2109 
2110 
2111 /* ********************** Receiving ********************** */
2112 
2113 
2122 
2127 
2131  const union UdpAddress *udp_addr;
2132 
2137 };
2138 
2139 
2150 static int
2152  struct GNUNET_CONTAINER_HeapNode *node,
2153  void *element,
2155 {
2156  struct FindReceiveContext *frc = cls;
2157  struct DefragContext *e = element;
2158 
2159  if ((frc->udp_addr_len == e->udp_addr_len) &&
2160  (0 == memcmp(frc->udp_addr, e->udp_addr, frc->udp_addr_len)))
2161  {
2162  frc->rc = e;
2163  return GNUNET_NO;
2164  }
2165  return GNUNET_YES;
2166 }
2167 
2168 
2177 static int
2179 {
2180  struct Plugin *plugin = cls;
2181  struct UDP_MessageWrapper *udpw;
2182  struct UDP_MessageWrapper *next;
2183  struct FindReceiveContext frc;
2184 
2187  "Session %p to peer `%s' at address %s ended\n",
2188  s,
2189  GNUNET_i2s(&s->target),
2190  udp_address_to_string(plugin,
2191  s->address->address,
2192  s->address->address_length));
2193  if (NULL != s->timeout_task)
2194  {
2196  s->timeout_task = NULL;
2197  }
2198  if (NULL != s->frag_ctx)
2199  {
2200  /* Remove fragmented message due to disconnect */
2202  }
2203  GNUNET_assert(
2204  GNUNET_YES ==
2206  frc.rc = NULL;
2207  frc.udp_addr = s->address->address;
2209  /* Lookup existing receive context for this address */
2210  if (NULL != plugin->defrag_ctxs)
2211  {
2214  &frc);
2215  if (NULL != frc.rc)
2216  {
2217  struct DefragContext *d_ctx = frc.rc;
2218 
2221  GNUNET_free(d_ctx);
2222  }
2223  }
2224  s->in_destroy = GNUNET_YES;
2225  next = plugin->ipv4_queue_head;
2226  while (NULL != (udpw = next))
2227  {
2228  next = udpw->next;
2229  if (udpw->session == s)
2230  {
2231  dequeue(plugin, udpw);
2232  udpw->qc(udpw->qc_cls, udpw, GNUNET_SYSERR);
2233  GNUNET_free(udpw);
2234  }
2235  }
2236  next = plugin->ipv6_queue_head;
2237  while (NULL != (udpw = next))
2238  {
2239  next = udpw->next;
2240  if (udpw->session == s)
2241  {
2242  dequeue(plugin, udpw);
2243  udpw->qc(udpw->qc_cls, udpw, GNUNET_SYSERR);
2244  GNUNET_free(udpw);
2245  }
2246  }
2247  if ((NULL != s->frag_ctx) && (NULL != s->frag_ctx->cont))
2248  {
2249  /* The 'frag_ctx' itself will be freed in #free_session() a bit
2250  later, as it might be in use right now */
2252  "Calling continuation for fragemented message to `%s' with result SYSERR\n",
2253  GNUNET_i2s(&s->target));
2254  s->frag_ctx->cont(s->frag_ctx->cont_cls,
2255  &s->target,
2256  GNUNET_SYSERR,
2257  s->frag_ctx->payload_size,
2258  s->frag_ctx->on_wire_size);
2259  }
2261  plugin->env->session_end(plugin->env->cls, s->address, s);
2262  GNUNET_STATISTICS_set(plugin->env->stats,
2263  "# UDP sessions active",
2265  GNUNET_NO);
2266  if (0 == s->rc)
2267  free_session(s);
2268  return GNUNET_OK;
2269 }
2270 
2271 
2280 static void
2282  const struct GNUNET_MessageHeader *msg,
2283  const union UdpAddress *udp_addr,
2284  socklen_t udp_addr_len)
2285 {
2286  const struct GNUNET_MessageHeader *ack;
2287  const struct UDP_ACK_Message *udp_ack;
2288  struct GNUNET_HELLO_Address *address;
2289  struct GNUNET_ATS_Session *s;
2290  struct GNUNET_TIME_Relative flow_delay;
2291 
2292  /* check message format */
2293  if (ntohs(msg->size) <
2294  sizeof(struct UDP_ACK_Message) + sizeof(struct GNUNET_MessageHeader))
2295  {
2296  GNUNET_break_op(0);
2297  return;
2298  }
2299  udp_ack = (const struct UDP_ACK_Message *)msg;
2300  ack = (const struct GNUNET_MessageHeader *)&udp_ack[1];
2301  if (ntohs(ack->size) != ntohs(msg->size) - sizeof(struct UDP_ACK_Message))
2302  {
2303  GNUNET_break_op(0);
2304  return;
2305  }
2306 
2307  /* Locate session */
2308  address = GNUNET_HELLO_address_allocate(&udp_ack->sender,
2309  PLUGIN_NAME,
2310  udp_addr,
2311  udp_addr_len,
2313  s = udp_plugin_lookup_session(plugin, address);
2314  if (NULL == s)
2315  {
2317  "UDP session of address %s for ACK not found\n",
2318  udp_address_to_string(plugin,
2319  address->address,
2320  address->address_length));
2321  GNUNET_HELLO_address_free(address);
2322  return;
2323  }
2324  if (NULL == s->frag_ctx)
2325  {
2327  "Fragmentation context of address %s for ACK (%s) not found\n",
2328  udp_address_to_string(plugin,
2329  address->address,
2330  address->address_length),
2332  GNUNET_HELLO_address_free(address);
2333  return;
2334  }
2335  GNUNET_HELLO_address_free(address);
2336 
2337  /* evaluate flow delay: how long should we wait between messages? */
2338  if (UINT32_MAX == ntohl(udp_ack->delay))
2339  {
2340  /* Other peer asked for us to terminate the session */
2342  "Asked to disconnect UDP session of %s\n",
2343  GNUNET_i2s(&udp_ack->sender));
2344  udp_disconnect_session(plugin, s);
2345  return;
2346  }
2347  flow_delay.rel_value_us = (uint64_t)ntohl(udp_ack->delay);
2348  if (flow_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
2350  "We received a sending delay of %s for %s\n",
2352  GNUNET_i2s(&udp_ack->sender));
2353  else
2355  "We received a sending delay of %s for %s\n",
2357  GNUNET_i2s(&udp_ack->sender));
2358  /* Flow delay is for the reassembled packet, however, our delay
2359  is per packet, so we need to adjust: */
2360  s->flow_delay_from_other_peer = flow_delay;
2361 
2362  /* Handle ACK */
2364  {
2366  "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
2367  (unsigned int)ntohs(msg->size),
2368  GNUNET_i2s(&udp_ack->sender),
2369  udp_address_to_string(plugin, udp_addr, udp_addr_len));
2370  /* Expect more ACKs to arrive */
2371  return;
2372  }
2373 
2374  /* Remove fragmented message after successful sending */
2376  "Message from %s at %s full ACK'ed\n",
2377  GNUNET_i2s(&udp_ack->sender),
2378  udp_address_to_string(plugin, udp_addr, udp_addr_len));
2380 }
2381 
2382 
2391 static int
2393  const struct GNUNET_MessageHeader *hdr)
2394 {
2395  struct GNUNET_ATS_Session *session = cls;
2396  struct Plugin *plugin = session->plugin;
2397 
2398  if (GNUNET_YES == session->in_destroy)
2399  return GNUNET_OK;
2400  reschedule_session_timeout(session);
2401  session->flow_delay_for_other_peer =
2402  plugin->env->receive(plugin->env->cls, session->address, session, hdr);
2403  return GNUNET_OK;
2404 }
2405 
2406 
2415 static int
2417  const struct GNUNET_PeerIdentity *key,
2418  void *value)
2419 {
2420  struct Plugin *plugin = cls;
2421 
2422  udp_disconnect_session(plugin, value);
2423  return GNUNET_OK;
2424 }
2425 
2426 
2435 static void
2436 udp_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
2437 {
2438  struct Plugin *plugin = cls;
2439 
2441  "Disconnecting from peer `%s'\n",
2442  GNUNET_i2s(target));
2444  target,
2446  plugin);
2447 }
2448 
2449 
2455 static void
2457 {
2458  struct GNUNET_ATS_Session *s = cls;
2459  struct Plugin *plugin = s->plugin;
2460  struct GNUNET_TIME_Relative left;
2461 
2462  s->timeout_task = NULL;
2464  if (left.rel_value_us > 0)
2465  {
2466  /* not actually our turn yet, but let's at least update
2467  the monitor, it may think we're about to die ... */
2470  return;
2471  }
2473  "Session %p was idle for %s, disconnecting\n",
2474  s,
2476  GNUNET_YES));
2477  /* call session destroy function */
2478  udp_disconnect_session(plugin, s);
2479 }
2480 
2481 
2493 static struct GNUNET_ATS_Session *
2495  const struct GNUNET_HELLO_Address *address,
2496  enum GNUNET_NetworkType network_type)
2497 {
2498  struct Plugin *plugin = cls;
2499  struct GNUNET_ATS_Session *s;
2500 
2501  s = GNUNET_new(struct GNUNET_ATS_Session);
2503  s->plugin = plugin;
2504  s->address = GNUNET_HELLO_address_copy(address);
2505  s->target = address->peer;
2513  s->timeout_task =
2515  s->scope = network_type;
2516 
2518  "Creating new session %p for peer `%s' address `%s'\n",
2519  s,
2520  GNUNET_i2s(&address->peer),
2521  udp_address_to_string(plugin,
2522  address->address,
2523  address->address_length));
2525  plugin->sessions,
2526  &s->target,
2527  s,
2529  GNUNET_STATISTICS_set(plugin->env->stats,
2530  "# UDP sessions active",
2532  GNUNET_NO);
2534  return s;
2535 }
2536 
2537 
2546 static struct GNUNET_ATS_Session *
2548 {
2549  struct Plugin *plugin = cls;
2550  struct GNUNET_ATS_Session *s;
2551  enum GNUNET_NetworkType network_type = GNUNET_NT_UNSPECIFIED;
2552  const struct IPv4UdpAddress *udp_v4;
2553  const struct IPv6UdpAddress *udp_v6;
2554 
2555  if (NULL == address)
2556  {
2557  GNUNET_break(0);
2558  return NULL;
2559  }
2560  if ((address->address_length != sizeof(struct IPv4UdpAddress)) &&
2561  (address->address_length != sizeof(struct IPv6UdpAddress)))
2562  {
2563  GNUNET_break_op(0);
2564  return NULL;
2565  }
2566  if (NULL != (s = udp_plugin_lookup_session(cls, address)))
2567  return s;
2568 
2569  /* need to create new session */
2570  if (sizeof(struct IPv4UdpAddress) == address->address_length)
2571  {
2572  struct sockaddr_in v4;
2573 
2574  udp_v4 = (const struct IPv4UdpAddress *)address->address;
2575  memset(&v4, '\0', sizeof(v4));
2576  v4.sin_family = AF_INET;
2577 #if HAVE_SOCKADDR_IN_SIN_LEN
2578  v4.sin_len = sizeof(struct sockaddr_in);
2579 #endif
2580  v4.sin_port = udp_v4->u4_port;
2581  v4.sin_addr.s_addr = udp_v4->ipv4_addr;
2582  network_type = plugin->env->get_address_type(plugin->env->cls,
2583  (const struct sockaddr *)&v4,
2584  sizeof(v4));
2585  }
2586  if (sizeof(struct IPv6UdpAddress) == address->address_length)
2587  {
2588  struct sockaddr_in6 v6;
2589 
2590  udp_v6 = (const struct IPv6UdpAddress *)address->address;
2591  memset(&v6, '\0', sizeof(v6));
2592  v6.sin6_family = AF_INET6;
2593 #if HAVE_SOCKADDR_IN_SIN_LEN
2594  v6.sin6_len = sizeof(struct sockaddr_in6);
2595 #endif
2596  v6.sin6_port = udp_v6->u6_port;
2597  v6.sin6_addr = udp_v6->ipv6_addr;
2598  network_type = plugin->env->get_address_type(plugin->env->cls,
2599  (const struct sockaddr *)&v6,
2600  sizeof(v6));
2601  }
2602  GNUNET_break(GNUNET_NT_UNSPECIFIED != network_type);
2603  return udp_plugin_create_session(cls, address, network_type);
2604 }
2605 
2606 
2616 static void
2618  const struct UDPMessage *msg,
2619  const union UdpAddress *udp_addr,
2620  size_t udp_addr_len,
2621  enum GNUNET_NetworkType network_type)
2622 {
2623  struct GNUNET_ATS_Session *s;
2624  struct GNUNET_HELLO_Address *address;
2625 
2626  GNUNET_break(GNUNET_NT_UNSPECIFIED != network_type);
2627  if (0 != ntohl(msg->reserved))
2628  {
2629  GNUNET_break_op(0);
2630  return;
2631  }
2632  if (ntohs(msg->header.size) <
2633  sizeof(struct GNUNET_MessageHeader) + sizeof(struct UDPMessage))
2634  {
2635  GNUNET_break_op(0);
2636  return;
2637  }
2638 
2639  address = GNUNET_HELLO_address_allocate(&msg->sender,
2640  PLUGIN_NAME,
2641  udp_addr,
2642  udp_addr_len,
2644  if (NULL == (s = udp_plugin_lookup_session(plugin, address)))
2645  {
2646  s = udp_plugin_create_session(plugin, address, network_type);
2647  plugin->env->session_start(plugin->env->cls, address, s, s->scope);
2649  }
2650  GNUNET_free(address);
2651 
2652  s->rc++;
2654  (const char *)&msg[1],
2655  ntohs(msg->header.size) - sizeof(struct UDPMessage),
2656  GNUNET_YES,
2657  GNUNET_NO);
2658  s->rc--;
2659  if ((0 == s->rc) && (GNUNET_YES == s->in_destroy))
2660  free_session(s);
2661 }
2662 
2663 
2670 static void
2671 fragment_msg_proc(void *cls, const struct GNUNET_MessageHeader *msg)
2672 {
2673  struct DefragContext *dc = cls;
2674  const struct UDPMessage *um;
2675 
2677  {
2678  GNUNET_break_op(0);
2679  return;
2680  }
2681  if (ntohs(msg->size) < sizeof(struct UDPMessage))
2682  {
2683  GNUNET_break_op(0);
2684  return;
2685  }
2686  um = (const struct UDPMessage *)msg;
2687  dc->sender = um->sender;
2688  dc->have_sender = GNUNET_YES;
2690  um,
2691  dc->udp_addr,
2692  dc->udp_addr_len,
2693  dc->network_type);
2694 }
2695 
2696 
2706 static void
2707 ack_message_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
2708 {
2709  struct Plugin *plugin = cls;
2710 
2711  if (GNUNET_OK == result)
2712  {
2713  GNUNET_STATISTICS_update(plugin->env->stats,
2714  "# UDP, ACK messages sent",
2715  1,
2716  GNUNET_NO);
2717  }
2718  else
2719  {
2720  GNUNET_STATISTICS_update(plugin->env->stats,
2721  "# UDP, ACK transmissions failed",
2722  1,
2723  GNUNET_NO);
2724  }
2725 }
2726 
2727 
2735 static void
2736 ack_proc(void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
2737 {
2738  struct DefragContext *rc = cls;
2739  struct Plugin *plugin = rc->plugin;
2740  size_t msize = sizeof(struct UDP_ACK_Message) + ntohs(msg->size);
2741  struct UDP_ACK_Message *udp_ack;
2742  uint32_t delay;
2743  struct UDP_MessageWrapper *udpw;
2744  struct GNUNET_ATS_Session *s;
2745  struct GNUNET_HELLO_Address *address;
2746 
2747  if (GNUNET_NO == rc->have_sender)
2748  {
2749  /* tried to defragment but never succeeded, hence will not ACK */
2750  /* This can happen if we just lost msgs */
2751  GNUNET_STATISTICS_update(plugin->env->stats,
2752  "# UDP, fragments discarded without ACK",
2753  1,
2754  GNUNET_NO);
2755  return;
2756  }
2757  address = GNUNET_HELLO_address_allocate(&rc->sender,
2758  PLUGIN_NAME,
2759  rc->udp_addr,
2760  rc->udp_addr_len,
2762  s = udp_plugin_lookup_session(plugin, address);
2763  GNUNET_HELLO_address_free(address);
2764  if (NULL == s)
2765  {
2767  "Trying to transmit ACK to peer `%s' but no session found!\n",
2768  udp_address_to_string(plugin, rc->udp_addr, rc->udp_addr_len));
2771  GNUNET_free(rc);
2772  GNUNET_STATISTICS_update(plugin->env->stats,
2773  "# UDP, ACK transmissions failed",
2774  1,
2775  GNUNET_NO);
2776  return;
2777  }
2778  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us ==
2780  delay = UINT32_MAX;
2781  else if (s->flow_delay_for_other_peer.rel_value_us < UINT32_MAX)
2783  else
2784  delay = UINT32_MAX - 1; /* largest value we can communicate */
2786  "Sending ACK to `%s' including delay of %s\n",
2787  udp_address_to_string(plugin, rc->udp_addr, rc->udp_addr_len),
2789  GNUNET_YES));
2790  udpw = GNUNET_malloc(sizeof(struct UDP_MessageWrapper) + msize);
2791  udpw->msg_size = msize;
2792  udpw->payload_size = 0;
2793  udpw->session = s;
2796  udpw->msg_buf = (char *)&udpw[1];
2797  udpw->qc = &ack_message_sent;
2798  udpw->qc_cls = plugin;
2799  udp_ack = (struct UDP_ACK_Message *)udpw->msg_buf;
2800  udp_ack->header.size = htons((uint16_t)msize);
2802  udp_ack->delay = htonl(delay);
2803  udp_ack->sender = *plugin->env->my_identity;
2804  GNUNET_memcpy(&udp_ack[1], msg, ntohs(msg->size));
2805  enqueue(plugin, udpw);
2807  if (s->address->address_length == sizeof(struct IPv4UdpAddress))
2808  schedule_select_v4(plugin);
2809  else
2810  schedule_select_v6(plugin);
2811 }
2812 
2813 
2823 static void
2825  const struct GNUNET_MessageHeader *msg,
2826  const union UdpAddress *udp_addr,
2827  size_t udp_addr_len,
2828  enum GNUNET_NetworkType network_type)
2829 {
2830  struct DefragContext *d_ctx;
2831  struct GNUNET_TIME_Absolute now;
2832  struct FindReceiveContext frc;
2833 
2834  frc.rc = NULL;
2835  frc.udp_addr = udp_addr;
2836  frc.udp_addr_len = udp_addr_len;
2837 
2838  /* Lookup existing receive context for this address */
2841  &frc);
2842  now = GNUNET_TIME_absolute_get();
2843  d_ctx = frc.rc;
2844 
2845  if (NULL == d_ctx)
2846  {
2847  /* Create a new defragmentation context */
2848  d_ctx = GNUNET_malloc(sizeof(struct DefragContext) + udp_addr_len);
2849  GNUNET_memcpy(&d_ctx[1], udp_addr, udp_addr_len);
2850  d_ctx->udp_addr = (const union UdpAddress *)&d_ctx[1];
2851  d_ctx->udp_addr_len = udp_addr_len;
2852  d_ctx->network_type = network_type;
2853  d_ctx->plugin = plugin;
2854  d_ctx->defrag =
2855  GNUNET_DEFRAGMENT_context_create(plugin->env->stats,
2856  UDP_MTU,
2858  d_ctx,
2860  &ack_proc);
2862  d_ctx,
2864  now.abs_value_us);
2866  "Created new defragmentation context for %u-byte fragment from `%s'\n",
2867  (unsigned int)ntohs(msg->size),
2868  udp_address_to_string(plugin, udp_addr, udp_addr_len));
2869  }
2870  else
2871  {
2873  "Found existing defragmentation context for %u-byte fragment from `%s'\n",
2874  (unsigned int)ntohs(msg->size),
2875  udp_address_to_string(plugin, udp_addr, udp_addr_len));
2876  }
2877 
2879  {
2880  /* keep this 'rc' from expiring */
2883  now.abs_value_us);
2884  }
2887  {
2888  /* remove 'rc' that was inactive the longest */
2890  GNUNET_assert(NULL != d_ctx);
2892  GNUNET_free(d_ctx);
2893  GNUNET_STATISTICS_update(plugin->env->stats,
2894  "# UDP, Defragmentations aborted",
2895  1,
2896  GNUNET_NO);
2897  }
2898 }
2899 
2900 
2907 static void
2909 {
2910  socklen_t fromlen;
2911  struct sockaddr_storage addr;
2912  char buf[65536] GNUNET_ALIGN;
2913  ssize_t size;
2914  const struct GNUNET_MessageHeader *msg;
2915  struct IPv4UdpAddress v4;
2916  struct IPv6UdpAddress v6;
2917  const struct sockaddr *sa;
2918  const struct sockaddr_in *sa4;
2919  const struct sockaddr_in6 *sa6;
2920  const union UdpAddress *int_addr;
2921  size_t int_addr_len;
2922  enum GNUNET_NetworkType network_type;
2923 
2924  fromlen = sizeof(addr);
2925  memset(&addr, 0, sizeof(addr));
2926  size = GNUNET_NETWORK_socket_recvfrom(rsock,
2927  buf,
2928  sizeof(buf),
2929  (struct sockaddr *)&addr,
2930  &fromlen);
2931  sa = (const struct sockaddr *)&addr;
2932 
2933  if (-1 == size)
2934  {
2936  "UDP failed to receive data: %s\n",
2937  strerror(errno));
2938  /* Connection failure or something. Not a protocol violation. */
2939  return;
2940  }
2941 
2942  /* Check if this is a STUN packet */
2943  if (GNUNET_NO !=
2945  (const struct sockaddr *)&addr,
2946  fromlen,
2947  buf,
2948  size))
2949  return; /* was STUN, do not process further */
2950 
2951  if (size < sizeof(struct GNUNET_MessageHeader))
2952  {
2954  "UDP got %u bytes from %s, which is not enough for a GNUnet message header\n",
2955  (unsigned int)size,
2956  GNUNET_a2s(sa, fromlen));
2957  /* _MAY_ be a connection failure (got partial message) */
2958  /* But it _MAY_ also be that the other side uses non-GNUnet protocol. */
2959  GNUNET_break_op(0);
2960  return;
2961  }
2962 
2963  msg = (const struct GNUNET_MessageHeader *)buf;
2965  "UDP received %u-byte message from `%s' type %u\n",
2966  (unsigned int)size,
2967  GNUNET_a2s(sa, fromlen),
2968  ntohs(msg->type));
2969  if (size != ntohs(msg->size))
2970  {
2972  "UDP malformed message (size %u) header from %s\n",
2973  (unsigned int)size,
2974  GNUNET_a2s(sa, fromlen));
2975  GNUNET_break_op(0);
2976  return;
2977  }
2978  GNUNET_STATISTICS_update(plugin->env->stats,
2979  "# UDP, total bytes received",
2980  size,
2981  GNUNET_NO);
2982  network_type = plugin->env->get_address_type(plugin->env->cls, sa, fromlen);
2983  switch (sa->sa_family)
2984  {
2985  case AF_INET:
2986  sa4 = (const struct sockaddr_in *)&addr;
2987  v4.options = 0;
2988  v4.ipv4_addr = sa4->sin_addr.s_addr;
2989  v4.u4_port = sa4->sin_port;
2990  int_addr = (union UdpAddress *)&v4;
2991  int_addr_len = sizeof(v4);
2992  break;
2993 
2994  case AF_INET6:
2995  sa6 = (const struct sockaddr_in6 *)&addr;
2996  v6.options = 0;
2997  v6.ipv6_addr = sa6->sin6_addr;
2998  v6.u6_port = sa6->sin6_port;
2999  int_addr = (union UdpAddress *)&v6;
3000  int_addr_len = sizeof(v6);
3001  break;
3002 
3003  default:
3004  GNUNET_break(0);
3005  return;
3006  }
3007 
3008  switch (ntohs(msg->type))
3009  {
3012  udp_broadcast_receive(plugin,
3013  buf,
3014  size,
3015  int_addr,
3016  int_addr_len,
3017  network_type);
3018  return;
3019 
3021  if (ntohs(msg->size) < sizeof(struct UDPMessage))
3022  {
3023  GNUNET_break_op(0);
3024  return;
3025  }
3026  process_udp_message(plugin,
3027  (const struct UDPMessage *)msg,
3028  int_addr,
3029  int_addr_len,
3030  network_type);
3031  return;
3032 
3034  read_process_ack(plugin, msg, int_addr, int_addr_len);
3035  return;
3036 
3038  read_process_fragment(plugin, msg, int_addr, int_addr_len, network_type);
3039  return;
3040 
3041  default:
3042  GNUNET_break_op(0);
3043  return;
3044  }
3045 }
3046 
3047 
3057 static struct UDP_MessageWrapper *
3059  struct GNUNET_NETWORK_Handle *sock)
3060 {
3061  struct UDP_MessageWrapper *udpw;
3062  struct GNUNET_TIME_Relative remaining;
3063  struct GNUNET_ATS_Session *session;
3064  int removed;
3065 
3066  removed = GNUNET_NO;
3067  udpw = (sock == plugin->sockv4) ? plugin->ipv4_queue_head
3068  : plugin->ipv6_queue_head;
3069  while (NULL != udpw)
3070  {
3071  session = udpw->session;
3072  /* Find messages with timeout */
3073  remaining = GNUNET_TIME_absolute_get_remaining(udpw->timeout);
3074  if (GNUNET_TIME_UNIT_ZERO.rel_value_us == remaining.rel_value_us)
3075  {
3076  /* Message timed out */
3077  removed = GNUNET_YES;
3078  dequeue(plugin, udpw);
3079  udpw->qc(udpw->qc_cls, udpw, GNUNET_SYSERR);
3080  GNUNET_free(udpw);
3081 
3082  if (sock == plugin->sockv4)
3083  {
3084  udpw = plugin->ipv4_queue_head;
3085  }
3086  else if (sock == plugin->sockv6)
3087  {
3088  udpw = plugin->ipv6_queue_head;
3089  }
3090  else
3091  {
3092  GNUNET_break(0); /* should never happen */
3093  udpw = NULL;
3094  }
3095  GNUNET_STATISTICS_update(plugin->env->stats,
3096  "# messages discarded due to timeout",
3097  1,
3098  GNUNET_NO);
3099  }
3100  else
3101  {
3102  /* Message did not time out, check transmission time */
3104  if (0 == remaining.rel_value_us)
3105  {
3106  /* this message is not delayed */
3108  "Message for peer `%s' (%u bytes) is not delayed \n",
3109  GNUNET_i2s(&udpw->session->target),
3110  udpw->payload_size);
3111  break; /* Found message to send, break */
3112  }
3113  else
3114  {
3115  /* Message is delayed, try next */
3117  "Message for peer `%s' (%u bytes) is delayed for %s\n",
3118  GNUNET_i2s(&udpw->session->target),
3119  udpw->payload_size,
3121  udpw = udpw->next;
3122  }
3123  }
3124  }
3125  if (GNUNET_YES == removed)
3126  notify_session_monitor(session->plugin,
3127  session,
3129  return udpw;
3130 }
3131 
3132 
3142 static void
3144  const struct sockaddr *sa,
3145  socklen_t slen,
3146  int error)
3147 {
3148  enum GNUNET_NetworkType type;
3149 
3150  type = plugin->env->get_address_type(plugin->env->cls, sa, slen);
3151  if (((GNUNET_NT_LAN == type) || (GNUNET_NT_WAN == type)) &&
3152  ((ENETUNREACH == errno) || (ENETDOWN == errno)))
3153  {
3154  if (slen == sizeof(struct sockaddr_in))
3155  {
3156  /* IPv4: "Network unreachable" or "Network down"
3157  *
3158  * This indicates we do not have connectivity
3159  */
3161  _("UDP could not transmit message to `%s': "
3162  "Network seems down, please check your network configuration\n"),
3163  GNUNET_a2s(sa, slen));
3164  }
3165  if (slen == sizeof(struct sockaddr_in6))
3166  {
3167  /* IPv6: "Network unreachable" or "Network down"
3168  *
3169  * This indicates that this system is IPv6 enabled, but does not
3170  * have a valid global IPv6 address assigned or we do not have
3171  * connectivity
3172  */
3174  _(
3175  "UDP could not transmit IPv6 message! "
3176  "Please check your network configuration and disable IPv6 if your "
3177  "connection does not have a global IPv6 address\n"));
3178  }
3179  }
3180  else
3181  {
3183  "UDP could not transmit message to `%s': `%s'\n",
3184  GNUNET_a2s(sa, slen),
3185  strerror(error));
3186  }
3187 }
3188 
3189 
3197 static void
3199 {
3200  ssize_t sent;
3201  socklen_t slen;
3202  const struct sockaddr *a;
3203  const struct IPv4UdpAddress *u4;
3204  struct sockaddr_in a4;
3205  const struct IPv6UdpAddress *u6;
3206  struct sockaddr_in6 a6;
3207  struct UDP_MessageWrapper *udpw;
3208 
3209  /* Find message(s) to send */
3210  while (NULL != (udpw = remove_timeout_messages_and_select(plugin, sock)))
3211  {
3212  if (sizeof(struct IPv4UdpAddress) ==
3213  udpw->session->address->address_length)
3214  {
3215  u4 = udpw->session->address->address;
3216  memset(&a4, 0, sizeof(a4));
3217  a4.sin_family = AF_INET;
3218 #if HAVE_SOCKADDR_IN_SIN_LEN
3219  a4.sin_len = sizeof(a4);
3220 #endif
3221  a4.sin_port = u4->u4_port;
3222  a4.sin_addr.s_addr = u4->ipv4_addr;
3223  a = (const struct sockaddr *)&a4;
3224  slen = sizeof(a4);
3225  }
3226  else if (sizeof(struct IPv6UdpAddress) ==
3227  udpw->session->address->address_length)
3228  {
3229  u6 = udpw->session->address->address;
3230  memset(&a6, 0, sizeof(a6));
3231  a6.sin6_family = AF_INET6;
3232 #if HAVE_SOCKADDR_IN_SIN_LEN
3233  a6.sin6_len = sizeof(a6);
3234 #endif
3235  a6.sin6_port = u6->u6_port;
3236  a6.sin6_addr = u6->ipv6_addr;
3237  a = (const struct sockaddr *)&a6;
3238  slen = sizeof(a6);
3239  }
3240  else
3241  {
3242  GNUNET_break(0);
3243  dequeue(plugin, udpw);
3244  udpw->qc(udpw->qc_cls, udpw, GNUNET_SYSERR);
3245  notify_session_monitor(plugin,
3246  udpw->session,
3248  GNUNET_free(udpw);
3249  continue;
3250  }
3251  sent = GNUNET_NETWORK_socket_sendto(sock,
3252  udpw->msg_buf,
3253  udpw->msg_size,
3254  a,
3255  slen);
3256  udpw->session->last_transmit_time =
3258  udpw->session->last_transmit_time);
3259  dequeue(plugin, udpw);
3260  if (GNUNET_SYSERR == sent)
3261  {
3262  /* Failure */
3263  analyze_send_error(plugin, a, slen, errno);
3264  udpw->qc(udpw->qc_cls, udpw, GNUNET_SYSERR);
3265  GNUNET_STATISTICS_update(plugin->env->stats,
3266  "# UDP, total, bytes, sent, failure",
3267  sent,
3268  GNUNET_NO);
3269  GNUNET_STATISTICS_update(plugin->env->stats,
3270  "# UDP, total, messages, sent, failure",
3271  1,
3272  GNUNET_NO);
3273  }
3274  else
3275  {
3276  /* Success */
3278  "UDP transmitted %u-byte message to `%s' `%s' (%d: %s)\n",
3279  (unsigned int)(udpw->msg_size),
3280  GNUNET_i2s(&udpw->session->target),
3281  GNUNET_a2s(a, slen),
3282  (int)sent,
3283  (sent < 0) ? strerror(errno) : "ok");
3284  GNUNET_STATISTICS_update(plugin->env->stats,
3285  "# UDP, total, bytes, sent, success",
3286  sent,
3287  GNUNET_NO);
3288  GNUNET_STATISTICS_update(plugin->env->stats,
3289  "# UDP, total, messages, sent, success",
3290  1,
3291  GNUNET_NO);
3292  if (NULL != udpw->frag_ctx)
3293  udpw->frag_ctx->on_wire_size += udpw->msg_size;
3294  udpw->qc(udpw->qc_cls, udpw, GNUNET_OK);
3295  }
3297  GNUNET_free(udpw);
3298  }
3299 }
3300 
3301 
3302 /* ***************** Event loop (part 2) *************** */
3303 
3304 
3312 static void
3314 {
3315  struct Plugin *plugin = cls;
3316  const struct GNUNET_SCHEDULER_TaskContext *tc;
3317 
3318  plugin->select_task_v4 = NULL;
3319  if (NULL == plugin->sockv4)
3320  return;
3322  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
3324  udp_select_read(plugin, plugin->sockv4);
3325  udp_select_send(plugin, plugin->sockv4);
3326  schedule_select_v4(plugin);
3327 }
3328 
3329 
3337 static void
3339 {
3340  struct Plugin *plugin = cls;
3341  const struct GNUNET_SCHEDULER_TaskContext *tc;
3342 
3343  plugin->select_task_v6 = NULL;
3344  if (NULL == plugin->sockv6)
3345  return;
3347  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
3349  udp_select_read(plugin, plugin->sockv6);
3350 
3351  udp_select_send(plugin, plugin->sockv6);
3352  schedule_select_v6(plugin);
3353 }
3354 
3355 
3356 /* ******************* Initialization *************** */
3357 
3358 
3367 static unsigned int
3369  const struct sockaddr_in6 *bind_v6,
3370  const struct sockaddr_in *bind_v4)
3371 {
3372  int tries;
3373  unsigned int sockets_created = 0;
3374  struct sockaddr_in6 server_addrv6;
3375  struct sockaddr_in server_addrv4;
3376  const struct sockaddr *server_addr;
3377  const struct sockaddr *addrs[2];
3378  socklen_t addrlens[2];
3379  socklen_t addrlen;
3380  int eno;
3381 
3382  /* Create IPv6 socket */
3383  eno = EINVAL;
3384  if (GNUNET_YES == plugin->enable_ipv6)
3385  {
3386  plugin->sockv6 = GNUNET_NETWORK_socket_create(PF_INET6, SOCK_DGRAM, 0);
3387  if (NULL == plugin->sockv6)
3388  {
3390  _("Disabling IPv6 since it is not supported on this system!\n"));
3391  plugin->enable_ipv6 = GNUNET_NO;
3392  }
3393  else
3394  {
3395  memset(&server_addrv6, 0, sizeof(struct sockaddr_in6));
3396 #if HAVE_SOCKADDR_IN_SIN_LEN
3397  server_addrv6.sin6_len = sizeof(struct sockaddr_in6);
3398 #endif
3399  server_addrv6.sin6_family = AF_INET6;
3400  if (NULL != bind_v6)
3401  server_addrv6.sin6_addr = bind_v6->sin6_addr;
3402  else
3403  server_addrv6.sin6_addr = in6addr_any;
3404 
3405  if (0 == plugin->port) /* autodetect */
3406  server_addrv6.sin6_port = htons(
3408  32000);
3409  else
3410  server_addrv6.sin6_port = htons(plugin->port);
3411  addrlen = sizeof(struct sockaddr_in6);
3412  server_addr = (const struct sockaddr *)&server_addrv6;
3413 
3414  tries = 0;
3415  while (tries < 10)
3416  {
3418  "Binding to IPv6 `%s'\n",
3419  GNUNET_a2s(server_addr, addrlen));
3420  /* binding */
3421  if (GNUNET_OK ==
3422  GNUNET_NETWORK_socket_bind(plugin->sockv6, server_addr, addrlen))
3423  break;
3424  eno = errno;
3425  if (0 != plugin->port)
3426  {
3427  tries = 10; /* fail immediately */
3428  break; /* bind failed on specific port */
3429  }
3430  /* autodetect */
3431  server_addrv6.sin6_port = htons(
3433  32000);
3434  tries++;
3435  }
3436  if (tries >= 10)
3437  {
3439  plugin->enable_ipv6 = GNUNET_NO;
3440  plugin->sockv6 = NULL;
3441  }
3442  else
3443  {
3444  plugin->port = ntohs(server_addrv6.sin6_port);
3445  }
3446  if (NULL != plugin->sockv6)
3447  {
3449  "IPv6 UDP socket created listinging at %s\n",
3450  GNUNET_a2s(server_addr, addrlen));
3451  addrs[sockets_created] = server_addr;
3452  addrlens[sockets_created] = addrlen;
3453  sockets_created++;
3454  }
3455  else
3456  {
3458  _("Failed to bind UDP socket to %s: %s\n"),
3459  GNUNET_a2s(server_addr, addrlen),
3460  strerror(eno));
3461  }
3462  }
3463  }
3464 
3465  /* Create IPv4 socket */
3466  eno = EINVAL;
3467  plugin->sockv4 = GNUNET_NETWORK_socket_create(PF_INET, SOCK_DGRAM, 0);
3468  if (NULL == plugin->sockv4)
3469  {
3472  _("Disabling IPv4 since it is not supported on this system!\n"));
3473  plugin->enable_ipv4 = GNUNET_NO;
3474  }
3475  else
3476  {
3477  memset(&server_addrv4, 0, sizeof(struct sockaddr_in));
3478 #if HAVE_SOCKADDR_IN_SIN_LEN
3479  server_addrv4.sin_len = sizeof(struct sockaddr_in);
3480 #endif
3481  server_addrv4.sin_family = AF_INET;
3482  if (NULL != bind_v4)
3483  server_addrv4.sin_addr = bind_v4->sin_addr;
3484  else
3485  server_addrv4.sin_addr.s_addr = INADDR_ANY;
3486 
3487  if (0 == plugin->port)
3488  /* autodetect */
3489  server_addrv4.sin_port = htons(
3491  else
3492  server_addrv4.sin_port = htons(plugin->port);
3493 
3494  addrlen = sizeof(struct sockaddr_in);
3495  server_addr = (const struct sockaddr *)&server_addrv4;
3496 
3497  tries = 0;
3498  while (tries < 10)
3499  {
3501  "Binding to IPv4 `%s'\n",
3502  GNUNET_a2s(server_addr, addrlen));
3503 
3504  /* binding */
3505  if (GNUNET_OK ==
3506  GNUNET_NETWORK_socket_bind(plugin->sockv4, server_addr, addrlen))
3507  break;
3508  eno = errno;
3509  if (0 != plugin->port)
3510  {
3511  tries = 10; /* fail */
3512  break; /* bind failed on specific port */
3513  }
3514 
3515  /* autodetect */
3516  server_addrv4.sin_port = htons(
3518  tries++;
3519  }
3520  if (tries >= 10)
3521  {
3523  plugin->enable_ipv4 = GNUNET_NO;
3524  plugin->sockv4 = NULL;
3525  }
3526  else
3527  {
3528  plugin->port = ntohs(server_addrv4.sin_port);
3529  }
3530 
3531  if (NULL != plugin->sockv4)
3532  {
3534  "IPv4 socket created on port %s\n",
3535  GNUNET_a2s(server_addr, addrlen));
3536  addrs[sockets_created] = server_addr;
3537  addrlens[sockets_created] = addrlen;
3538  sockets_created++;
3539  }
3540  else
3541  {
3543  _("Failed to bind UDP socket to %s: %s\n"),
3544  GNUNET_a2s(server_addr, addrlen),
3545  strerror(eno));
3546  }
3547  }
3548 
3549  if (0 == sockets_created)
3550  {
3551  LOG(GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n"));
3552  return 0; /* No sockets created, return */
3553  }
3554  schedule_select_v4(plugin);
3555  schedule_select_v6(plugin);
3556  plugin->nat = GNUNET_NAT_register(plugin->env->cfg,
3557  "transport-udp",
3558  IPPROTO_UDP,
3559  sockets_created,
3560  addrs,
3561  addrlens,
3563  NULL,
3564  plugin);
3565  return sockets_created;
3566 }
3567 
3568 
3576 void *
3578 {
3581  struct Plugin *p;
3582  unsigned long long port;
3583  unsigned long long aport;
3584  unsigned long long udp_max_bps;
3585  int enable_v6;
3586  int enable_broadcasting;
3587  int enable_broadcasting_recv;
3588  char *bind4_address;
3589  char *bind6_address;
3590  struct GNUNET_TIME_Relative interval;
3591  struct sockaddr_in server_addrv4;
3592  struct sockaddr_in6 server_addrv6;
3593  unsigned int res;
3594  int have_bind4;
3595  int have_bind6;
3596 
3597  if (NULL == env->receive)
3598  {
3599  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
3600  initialze the plugin or the API */
3602  api->cls = NULL;
3606  return api;
3607  }
3608 
3609  /* Get port number: port == 0 : autodetect a port,
3610  * > 0 : use this port, not given : 2086 default */
3612  "transport-udp",
3613  "PORT",
3614  &port))
3615  port = 2086;
3616  if (port > 65535)
3617  {
3619  "transport-udp",
3620  "PORT",
3621  _("must be in [0,65535]"));
3622  return NULL;
3623  }
3625  "transport-udp",
3626  "ADVERTISED_PORT",
3627  &aport))
3628  aport = port;
3629  if (aport > 65535)
3630  {
3632  "transport-udp",
3633  "ADVERTISED_PORT",
3634  _("must be in [0,65535]"));
3635  return NULL;
3636  }
3637 
3638  if (GNUNET_YES ==
3639  GNUNET_CONFIGURATION_get_value_yesno(env->cfg, "nat", "DISABLEV6"))
3640  enable_v6 = GNUNET_NO;
3641  else
3642  enable_v6 = GNUNET_YES;
3643 
3644  have_bind4 = GNUNET_NO;
3645  memset(&server_addrv4, 0, sizeof(server_addrv4));
3647  "transport-udp",
3648  "BINDTO",
3649  &bind4_address))
3650  {
3652  "Binding UDP plugin to specific address: `%s'\n",
3653  bind4_address);
3654  if (1 != inet_pton(AF_INET, bind4_address, &server_addrv4.sin_addr))
3655  {
3657  "transport-udp",
3658  "BINDTO",
3659  _("must be valid IPv4 address"));
3660  GNUNET_free(bind4_address);
3661  return NULL;
3662  }
3663  have_bind4 = GNUNET_YES;
3664  }
3665  GNUNET_free_non_null(bind4_address);
3666  have_bind6 = GNUNET_NO;
3667  memset(&server_addrv6, 0, sizeof(server_addrv6));
3669  "transport-udp",
3670  "BINDTO6",
3671  &bind6_address))
3672  {
3674  "Binding udp plugin to specific address: `%s'\n",
3675  bind6_address);
3676  if (1 != inet_pton(AF_INET6, bind6_address, &server_addrv6.sin6_addr))
3677  {
3679  "transport-udp",
3680  "BINDTO6",
3681  _("must be valid IPv6 address"));
3682  GNUNET_free(bind6_address);
3683  return NULL;
3684  }
3685  have_bind6 = GNUNET_YES;
3686  }
3687  GNUNET_free_non_null(bind6_address);
3688 
3689  enable_broadcasting = GNUNET_CONFIGURATION_get_value_yesno(env->cfg,
3690  "transport-udp",
3691  "BROADCAST");
3692  if (enable_broadcasting == GNUNET_SYSERR)
3693  enable_broadcasting = GNUNET_NO;
3694 
3695  enable_broadcasting_recv =
3697  "transport-udp",
3698  "BROADCAST_RECEIVE");
3699  if (enable_broadcasting_recv == GNUNET_SYSERR)
3700  enable_broadcasting_recv = GNUNET_YES;
3701 
3702  if (GNUNET_SYSERR ==
3704  "transport-udp",
3705  "BROADCAST_INTERVAL",
3706  &interval))
3707  {
3709  }
3711  "transport-udp",
3712  "MAX_BPS",
3713  &udp_max_bps))
3714  {
3715  /* 50 MB/s == infinity for practical purposes */
3716  udp_max_bps = 1024 * 1024 * 50;
3717  }
3718 
3719  p = GNUNET_new(struct Plugin);
3720  p->port = port;
3721  p->aport = aport;
3723  p->enable_ipv6 = enable_v6;
3724  p->enable_ipv4 = GNUNET_YES; /* default */
3725  p->enable_broadcasting = enable_broadcasting;
3726  p->enable_broadcasting_receiving = enable_broadcasting_recv;
3727  p->env = env;
3729  p->defrag_ctxs =
3732  NULL,
3733  NULL,
3735  (uint32_t)udp_max_bps),
3736  30);
3737  res = setup_sockets(p,
3738  (GNUNET_YES == have_bind6) ? &server_addrv6 : NULL,
3739  (GNUNET_YES == have_bind4) ? &server_addrv4 : NULL);
3740  if ((0 == res) || ((NULL == p->sockv4) && (NULL == p->sockv6)))
3741  {
3742  LOG(GNUNET_ERROR_TYPE_ERROR, _("Failed to create UDP network sockets\n"));
3745  if (NULL != p->nat)
3747  GNUNET_free(p);
3748  return NULL;
3749  }
3750 
3751  /* Setup broadcasting and receiving beacons */
3752  setup_broadcast(p, &server_addrv6, &server_addrv4);
3753 
3755  api->cls = p;
3764  api->send = &udp_plugin_send;
3769  return api;
3770 }
3771 
3772 
3783 static int
3785  struct GNUNET_CONTAINER_HeapNode *node,
3786  void *element,
3788 {
3789  struct DefragContext *d_ctx = element;
3790 
3793  GNUNET_free(d_ctx);
3794  return GNUNET_YES;
3795 }
3796 
3797 
3805 void *
3807 {
3808  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
3809  struct Plugin *plugin = api->cls;
3810  struct PrettyPrinterContext *cur;
3811  struct UDP_MessageWrapper *udpw;
3812 
3813  if (NULL == plugin)
3814  {
3815  GNUNET_free(api);
3816  return NULL;
3817  }
3818  stop_broadcast(plugin);
3819  if (NULL != plugin->select_task_v4)
3820  {
3822  plugin->select_task_v4 = NULL;
3823  }
3824  if (NULL != plugin->select_task_v6)
3825  {
3827  plugin->select_task_v6 = NULL;
3828  }
3829  if (NULL != plugin->sockv4)
3830  {
3832  plugin->sockv4 = NULL;
3833  }
3834  if (NULL != plugin->sockv6)
3835  {
3837  plugin->sockv6 = NULL;
3838  }
3839  if (NULL != plugin->nat)
3840  {
3841  GNUNET_NAT_unregister(plugin->nat);
3842  plugin->nat = NULL;
3843  }
3844  if (NULL != plugin->defrag_ctxs)
3845  {
3848  NULL);
3850  plugin->defrag_ctxs = NULL;
3851  }
3852  while (NULL != (udpw = plugin->ipv4_queue_head))
3853  {
3854  dequeue(plugin, udpw);
3855  udpw->qc(udpw->qc_cls, udpw, GNUNET_SYSERR);
3856  GNUNET_free(udpw);
3857  }
3858  while (NULL != (udpw = plugin->ipv6_queue_head))
3859  {
3860  dequeue(plugin, udpw);
3861  udpw->qc(udpw->qc_cls, udpw, GNUNET_SYSERR);
3862  GNUNET_free(udpw);
3863  }
3866  plugin);
3868 
3869  while (NULL != (cur = plugin->ppc_dll_head))
3870  {
3871  GNUNET_break(0);
3873  plugin->ppc_dll_tail,
3874  cur);
3876  if (NULL != cur->timeout_task)
3877  {
3879  cur->timeout_task = NULL;
3880  }
3881  GNUNET_free(cur);
3882  }
3883  GNUNET_free(plugin);
3884  GNUNET_free(api);
3885  return NULL;
3886 }
3887 
3888 /* end of plugin_transport_udp.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
size_t address_length
Number of bytes in address.
struct GNUNET_NAT_Handle * nat
NAT handle & address management.
struct GNUNET_TIME_Absolute last_transmit_time
What time did we last transmit?
size_t payload_size
Payload size of original message.
Session is being torn down and about to disappear.
static void ack_proc(void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
Transmit an acknowledgement.
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:737
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.
Local area network.
Definition: gnunet_nt_lib.h:49
uint32_t options
Optional options and flags for this address.
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
uint32_t num_bytes_pending
Number of bytes pending transmission for this session.
static int udp
Option -u: UDP requested.
Definition: gnunet-vpn.c:76
int enable_broadcasting
Is broadcasting enabled: GNUNET_YES or GNUNET_NO.
GNUNET_TRANSPORT_AddressStringCallback asc
Function to call with the result.
int GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
size_t payload_size
Payload size of original unfragmented message.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
GNUNET_TRANSPORT_AddressToString address_to_string
Function that will be called to convert a binary address to a string (numeric conversion only)...
struct UDP_MessageWrapper * ipv6_queue_head
Head of messages in IPv6 queue.
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_allocate(const struct GNUNET_PeerIdentity *peer, const char *transport_name, const void *address, size_t address_length, enum GNUNET_HELLO_AddressInfo local_info)
Allocate an address struct.
Definition: address.c:73
unsigned int rc
Reference counter to indicate that this session is currently being used and must not be destroyed; se...
struct UDP_FragmentationContext * prev
Previous in linked list.
void GNUNET_BANDWIDTH_tracker_init(struct GNUNET_BANDWIDTH_Tracker *av, GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb, void *update_cb_cls, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit, uint32_t max_carry_s)
Initialize bandwidth tracker.
Definition: bandwidth.c:302
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
uint64_t rel_value_us
The actual value.
const void * address
Binary representation of the address (plugin-specific).
struct GNUNET_ATS_Session * session
Session this message belongs to.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
static void enqueue(struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
Enqueue a message for transmission and update statistics.
struct PrettyPrinterContext * ppc_dll_tail
Running pretty printers: tail.
uint16_t aport
Port we advertise on.
Implementation of the UDP transport protocol.
common internal definitions for transport service
unsigned int msgs_in_queue
Number of messages waiting for transmission to this peer.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
void stop_broadcast(struct Plugin *plugin)
Stop broadcasting subsystem.
struct GNUNET_SCHEDULER_Task * timeout_task
Session timeout task.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
struct GNUNET_TIME_Relative flow_delay_for_other_peer
Desired delay for next sending we send to other peer.
The reading socket is ready.
Context information passed to each scheduler task.
static void free_session(struct GNUNET_ATS_Session *s)
Function to free last resources associated with a session.
struct Plugin * plugin
Pointer to the global plugin struct.
struct GNUNET_TIME_Absolute timeout
Message timeout.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
struct IPv4UdpAddress v4
IPv4 case.
GNUNET_TRANSPORT_DisconnectPeerFunction disconnect_peer
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
static void udp_plugin_select_v6(void *cls)
We have been notified that our readset has something to read.
const union UdpAddress * udp_addr
Address to find.
struct Plugin * plugin
The plugin.
char * bind6_address
Address we were told to bind to exclusively (IPv6).
int enable_ipv4
Is IPv4 enabled: GNUNET_YES or GNUNET_NO.
int is_inbound
GNUNET_YES if this is an inbound connection, GNUNET_NO if this is an outbound connection, GNUNET_SYSERR if connections of this plugin are so fundamentally bidirectional that they have no &#39;initiator&#39;
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
struct GNUNET_DEFRAGMENT_Context * GNUNET_DEFRAGMENT_context_create(struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, unsigned int num_msgs, void *cls, GNUNET_FRAGMENT_MessageProcessor proc, GNUNET_DEFRAGMENT_AckProcessor ackp)
Create a defragmentation context.
static struct GNUNET_ATS_Session * udp_plugin_lookup_session(void *cls, const struct GNUNET_HELLO_Address *address)
Locate an existing session the transport service is using to send data to another peer...
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
enum GNUNET_TRANSPORT_SessionState state
New state of the session.
struct GNUNET_MessageHeader header
Message header.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_RESOLVER_RequestHandle * resolver_handle
Resolver handle.
uint16_t u4_port
Port number, in network byte order.
UDP Message-Packet header (after defragmentation).
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Absolute transmission_time
Desired transmission time for this message, based on the flow limiting information we got from the ot...
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:410
GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
GNUNET_TRANSPORT_SessionMonitorSetup setup_monitor
Function to monitor the sessions managed by the plugin.
uint32_t reserved
Always zero for now.
int GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:474
Closure for append_port().
static void qc_message_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We are finished with a message from the message queue.
uint16_t port
Port to add after the IP address.
struct in6_addr ipv6_addr
IPv6 address.
struct GNUNET_FRAGMENT_Context * GNUNET_FRAGMENT_context_create(struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, struct GNUNET_BANDWIDTH_Tracker *tracker, struct GNUNET_TIME_Relative msg_delay, struct GNUNET_TIME_Relative ack_delay, const struct GNUNET_MessageHeader *msg, GNUNET_FRAGMENT_MessageProcessor proc, void *proc_cls)
Create a fragmentation context for the given message.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_CONSTANTS_LATENCY_WARN
After what amount of latency for a message do we print a warning?
static void read_process_ack(struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, const union UdpAddress *udp_addr, socklen_t udp_addr_len)
Handle a GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK message.
struct GNUNET_TIME_Absolute timeout
When does this session time out.
static struct Experiment * e
static void enqueue_fragment(void *cls, const struct GNUNET_MessageHeader *msg)
Function that is called with messages created by the fragmentation module.
static void fragmented_message_done(struct UDP_FragmentationContext *frag_ctx, int result)
We have completed our (attempt) to transmit a message that had to be fragmented – either because we ...
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
Wide area network (i.e.
Definition: gnunet_nt_lib.h:54
#define GNUNET_NO
Definition: gnunet_common.h:78
static int numeric
Option -n.
static int udp_plugin_check_address(void *cls, const void *addr, size_t addrlen)
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
static void ack_message_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We finished sending an acknowledgement.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
const struct GNUNET_NETWORK_FDSet * read_ready
Set of file descriptors ready for reading; note that additional bits may be set that were not in the ...
struct GNUNET_TIME_Relative flow_delay_from_other_peer
Desired delay for transmissions we received from other peer.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:393
int64_t bytes_in_buffer
Bytes currently in buffer.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void udp_plugin_update_session_timeout(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Session *session)
Function that will be called whenever the transport service wants to notify the plugin that a session...
struct GNUNET_HELLO_Address * address
Address.
static int process_inbound_tokenized_messages(void *cls, const struct GNUNET_MessageHeader *hdr)
Message tokenizer has broken up an incomming message.
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
int enable_broadcasting_receiving
Is receiving broadcasts enabled: GNUNET_YES or GNUNET_NO.
struct GNUNET_TIME_Relative last_expected_ack_delay
expected delay for ACKs
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
struct GNUNET_NETWORK_Handle * sockv4
The read socket for IPv4.
static ssize_t udp_plugin_send(void *cls, struct GNUNET_ATS_Session *s, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
Function that can be used by the transport service to transmit a message using the plugin...
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
const struct GNUNET_HELLO_Address * address
Address used by the session.
unsigned long long bytes_in_queue
Number of bytes waiting for transmission to this peer.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_get(const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls)
Perform a reverse DNS lookup.
void * asc_cls
Clsoure for asc.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
static void udp_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
Disconnect from a remote node.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define UDP_MTU
MTU for fragmentation subsystem.
uint16_t u6_port
Port number, in network byte order.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
uint64_t abs_value_us
The actual value.
enum GNUNET_SCHEDULER_Reason reason
Reason why the task is run now.
struct UDP_FragmentationContext * frag_ctx
Fragmentation context.
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:35
const char * GNUNET_FRAGMENT_print_ack(const struct GNUNET_MessageHeader *ack)
Convert an ACK message to a printable format suitable for logging.
uint32_t num_msg_pending
Number of messages pending transmission for this session.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
#define UDP_SESSION_TIME_OUT
After how much inactivity should a UDP session time out?
void GNUNET_FRAGMENT_context_transmission_done(struct GNUNET_FRAGMENT_Context *fc)
Continuation to call from the &#39;proc&#39; function after the fragment has been transmitted (and hence the ...
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
int GNUNET_NAT_test_address(struct GNUNET_NAT_Handle *nh, const void *addr, socklen_t addrlen)
Test if the given address is (currently) a plausible IP address for this peer.
Definition: nat_api.c:623
const union UdpAddress * udp_addr
Source address this receive context is for (allocated at the end of the struct).
static void append_port(void *cls, const char *hostname)
Append our port and forward the result.
GNUNET_TRANSPORT_PluginReceiveCallback receive
Function that should be called by the transport plugin whenever a message is received.
GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout
Function that will be called whenever the transport service wants to notify the plugin that a session...
static struct GNUNET_ATS_SolverFunctions * plugin
Our solver.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
Information about a plugin&#39;s session.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:130
Fragmentation context.
Definition: fragmentation.c:40
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1237
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
struct UDP_MessageWrapper * next
DLL of messages, next element.
enum GNUNET_NetworkType network_type
Network type the address belongs to.
Context to send fragmented messages.
struct GNUNET_SCHEDULER_Task * select_task_v4
ID of select task for IPv4.
void * cls
Closure for the various callbacks.
enum State state
current state of profiling
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
void * cls
Closure for all of the callbacks.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
struct GNUNET_TIME_Relative flow_delay_from_other_peer
Desired delay for transmissions we received from other peer.
static struct GNUNET_TIME_Relative interval
Definition: speedup.c:33
void GNUNET_DEFRAGMENT_context_destroy(struct GNUNET_DEFRAGMENT_Context *dc)
Destroy the given defragmentation context.
size_t on_wire_size
Bytes used to send all fragments on wire including UDP overhead.
void * libgnunet_plugin_transport_udp_done(void *cls)
The exported method.
Network format for IPv4 addresses.
static char * value
Value of the record to add/remove.
void(* GNUNET_TRANSPORT_AddressStringCallback)(void *cls, const char *address, int res)
Function called by the pretty printer for the resolved address for each human-readable address obtain...
GNUNET_TRANSPORT_StringToAddress string_to_address
Function that will be called to convert a string address to binary (numeric conversion only)...
void setup_broadcast(struct Plugin *plugin, struct sockaddr_in6 *server_addrv6, struct sockaddr_in *server_addrv4)
Setup broadcasting subsystem.
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:410
Information about ongoing sessions of the transport client.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
int GNUNET_NAT_stun_handle_packet(struct GNUNET_NAT_Handle *nh, const struct sockaddr *sender_addr, size_t sender_addr_len, const void *data, size_t data_size)
Handle an incoming STUN message.
Definition: nat_api.c:581
#define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE
Normal UDP message type.
uint32_t ipv4_addr
IPv4 address, in network byte order.
static struct GNUNET_NETWORK_Handle * bind_v6()
Create an IPv6 listen socket bound to our port.
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
int have_sender
Has the sender field been initialized yet?
static struct GNUNET_SCHEDULER_Task * t4
Task for IPv4 socket.
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task.
The transport service will pass a pointer to a struct of this type as the first and only argument to ...
static enum GNUNET_NetworkType scope
Which network scope do we belong to?
struct PrettyPrinterContext * prev
DLL.
GNUNET_TRANSPORT_GetNetworkType get_network
Function to obtain the network type for a session.
Handle to a message stream tokenizer.
Definition: mst.c:43
static void udp_plugin_setup_monitor(void *cls, GNUNET_TRANSPORT_SessionInfoCallback sic, void *sic_cls)
Begin monitoring sessions of a plugin.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:686
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:838
struct GNUNET_DEFRAGMENT_Context * defrag
Defragmentation context.
#define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
We keep a defragmentation queue per sender address.
static char buf[2048]
static enum GNUNET_NetworkType udp_plugin_get_network_for_address(void *cls, const struct GNUNET_HELLO_Address *address)
Function obtain the network type for an address.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition: time.c:317
struct GNUNET_MessageHeader header
Message header.
Closure for session_cmp_it().
static void udp_nat_port_map_callback(void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
Our external IP address/port mapping has changed.
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:84
void(* GNUNET_TRANSPORT_SessionInfoCallback)(void *cls, struct GNUNET_ATS_Session *session, const struct GNUNET_TRANSPORT_SessionInfo *info)
Function called by the plugin with information about the current sessions managed by the plugin (for ...
static int result
Global testing status.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:440
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
size_t udp_addr_len
Length of udp_addr.
struct GNUNET_PeerIdentity sender
What is the identity of the sender.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
int GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:113
struct GNUNET_TIME_Absolute session_timeout
At what time will this session timeout (unless activity happens)?
int in_destroy
Is this session about to be destroyed (sometimes we cannot destroy a session immediately as below us ...
static GNUNET_NETWORK_STRUCT_END void notify_session_monitor(struct Plugin *plugin, struct GNUNET_ATS_Session *session, enum GNUNET_TRANSPORT_SessionState state)
If a session monitor is attached, notify it about the new session state.
static int session_cmp_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Find a session with a matching address.
GNUNET_TRANSPORT_TransmitContinuation cont
External continuation to call upon completion of the transmission, NULL if this queue entry is not fo...
static int udp_string_to_address(void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added)
Function called to convert a string address to a binary address.
void * cont_cls
Closure for cont.
Heap with the minimum cost at the root.
struct GNUNET_ATS_Session * session
The session this fragmentation context belongs to.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
Information we track for each message in the queue.
static int udp_disconnect_session(void *cls, struct GNUNET_ATS_Session *s)
Functions with this signature are called whenever we need to close a session due to a disconnect or f...
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
Closure for find_receive_context().
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
void udp_broadcast_receive(struct Plugin *plugin, const char *buf, ssize_t size, const union UdpAddress *udp_addr, size_t udp_addr_len, enum GNUNET_NetworkType network_type)
We received a broadcast message.
static void fragment_msg_proc(void *cls, const struct GNUNET_MessageHeader *msg)
Process a defragmented message.
static int res
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
int GNUNET_FRAGMENT_process_ack(struct GNUNET_FRAGMENT_Context *fc, const struct GNUNET_MessageHeader *msg)
Process an acknowledgement message we got from the other side (to control re-transmits).
static void analyze_send_error(struct Plugin *plugin, const struct sockaddr *sa, socklen_t slen, int error)
We failed to transmit a message via UDP.
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer for inbound messages.
Defragmentation context (one per connection).
struct GNUNET_TIME_Relative broadcast_interval
Broadcast interval.
uint32_t options
Optional options and flags for this address.
static struct GNUNET_TIME_Absolute start_time
Start time of the current round; used to determine how long one iteration takes (which influences how...
struct DefragContext * rc
Where to store the result.
struct GNUNET_SCHEDULER_Task * select_task_v6
ID of select task for IPv6.
Node in the heap.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition: nat_api.c:690
static struct UDP_MessageWrapper * remove_timeout_messages_and_select(struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
Removes messages from the transmission queue that have timed out, and then selects a message that sho...
static void schedule_select_v6(struct Plugin *plugin)
(re)schedule IPv6-select tasks for this plugin.
Network format for IPv6 addresses.
struct IPv6UdpAddress v6
IPv6 case.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:66
uint64_t GNUNET_CONTAINER_HeapCostType
Cost by which elements in a heap can be ordered.
struct GNUNET_ATS_Session * session
Session associated with this context.
static enum GNUNET_NetworkType udp_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
Function obtain the network type for a session.
Handle to a request given to the resolver.
Definition: resolver_api.c:100
enum GNUNET_NetworkType scope
ATS network type.
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition: nat_api.c:376
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
Data structure to track defragmentation contexts based on the source of the UDP traffic.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
void(* GNUNET_TRANSPORT_TransmitContinuation)(void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire)
Function called by the GNUNET_TRANSPORT_TransmitFunction upon "completion".
static struct GNUNET_ATS_Session * udp_plugin_create_session(void *cls, const struct GNUNET_HELLO_Address *address, enum GNUNET_NetworkType network_type)
Allocate a new session for the given endpoint address.
static struct GNUNET_SCHEDULER_Task * timeout_task
Task to be run on timeout.
Definition: gnunet-arm.c:119
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
struct PrettyPrinterContext * next
DLL.
struct GNUNET_PeerIdentity peer
For which peer is this an address?
struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_init(uint32_t bytes_per_second)
Create a new bandwidth value.
Definition: bandwidth.c:39
static struct GNUNET_ATS_Session * udp_plugin_get_session(void *cls, const struct GNUNET_HELLO_Address *address)
Creates a new outbound session the transport service will use to send data to the peer...
static void dequeue(struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
Remove the given message from the transmission queue and update all applicable statistics.
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
uint32_t delay
Desired delay for flow control, in us (in NBO).
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
static int disconnect_and_free_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Destroy a session, plugin is being unloaded.
static void schedule_select_v4(struct Plugin *plugin)
(re)schedule IPv4-select tasks for this plugin.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK
UDP ACK.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
struct UDP_MessageWrapper * ipv4_queue_tail
Tail of messages in IPv4 queue.
size_t udp_addr_len
Number of bytes in udp_addr.
Allow multiple values with the same key.
static void process_udp_message(struct Plugin *plugin, const struct UDPMessage *msg, const union UdpAddress *udp_addr, size_t udp_addr_len, enum GNUNET_NetworkType network_type)
We&#39;ve received a UDP Message.
struct GNUNET_TIME_Absolute start_time
Message enqueue time.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
struct GNUNET_TIME_Absolute start_time
Start time.
This is just an update about the session, the state did not change.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
char * msg_buf
Message with msg_size bytes including UDP-specific overhead.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct UDP_FragmentationContext * next
Next in linked list.
GNUNET_TRANSPORT_QueryKeepaliveFactorFunction query_keepalive_factor
Function that is used to query keepalive factor.
The identity of the host (wraps the signing key of the peer).
No additional information.
static void session_timeout(void *cls)
Session was idle, so disconnect it.
int GNUNET_CONTAINER_multipeermap_contains_value(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Check if the map contains the given value under the given key.
static char * hostname
Our hostname; we give this to all the peers we start.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to &#39;struct&#39;s...
struct GNUNET_CONTAINER_HeapNode * hnode
Node in the defrag heap.
#define GNUNET_PACKED
gcc-ism to get packed structs.
static int find_receive_context(void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, GNUNET_CONTAINER_HeapCostType cost)
Scan the heap for a receive context with the given address.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:81
struct UDP_MessageWrapper * ipv6_queue_tail
Tail of messages in IPv6 queue.
static int heap_cleanup_iterator(void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, GNUNET_CONTAINER_HeapCostType cost)
Function called on each entry in the defragmentation heap to clean it up.
static void udp_plugin_select_v4(void *cls)
We have been notified that our readset has something to read.
Handle for a plugin.
Definition: block.c:37
uint32_t options
Address options.
void * cont_cls
Closure for cont.
void * qc_cls
Closure for qc.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:373
struct GNUNET_PeerIdentity target
To whom are we talking to.
#define PLUGIN_NAME
static void udp_plugin_address_pretty_printer(void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
Convert the transports address to a nice, human-readable format.
Either an IPv4 or IPv6 UDP address.
static struct GNUNET_NETWORK_Handle * bind_v4()
Create an IPv4 listen socket bound to our port.
An address for communicating with a peer.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:109
const char * udp_address_to_string(void *cls, const void *addr, size_t addrlen)
Function called for a quick conversion of the binary address to a numeric address.
#define GNUNET_log(kind,...)
The session was created (first call for each session object).
Entry in list of pending tasks.
Definition: scheduler.c:131
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
struct GNUNET_ATS_Session * sessions
List of open sessions (or peer map, or...)
struct GNUNET_NETWORK_Handle * sockv6
The read socket for IPv6.
uint16_t port
Port used.
handle to a socket
Definition: network.c:46
char * bind4_address
Address we were told to bind to exclusively (IPv4).
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
void * cls
Closure to use for callbacks.
static unsigned int udp_query_keepalive_factor(void *cls)
Function that is called to get the keepalive factor.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
GNUNET_TRANSPORT_AddressPrettyPrinter address_pretty_printer
Function to pretty-print addresses.
Header for all communications.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:525
struct GNUNET_CONTAINER_Heap * defrag_ctxs
Heap with all of our defragmentation activities.
int GNUNET_DEFRAGMENT_process_fragment(struct GNUNET_DEFRAGMENT_Context *dc, const struct GNUNET_MessageHeader *msg)
We have received a fragment.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
const struct GNUNET_HELLO_Address * address
Address we are looking for.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1467
UDP ACK Message-Packet header.
struct GNUNET_TIME_Relative last_expected_msg_delay
desired delay between UDP messages
QueueContinuation qc
Function to call once the message wrapper is being removed from the queue (with success or failure)...
struct GNUNET_ATS_Session * res
Set to session matching the address.
struct UDP_MessageWrapper * prev
DLL of messages, previous element.
struct PrettyPrinterContext * ppc_dll_head
Running pretty printers: head.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
struct GNUNET_BANDWIDTH_Tracker tracker
Bandwidth tracker to limit global UDP traffic.
#define GNUNET_MESSAGE_TYPE_FRAGMENT
FRAGMENT of a larger message.
uint32_t myoptions
Address options.
static void udp_select_send(struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
It is time to try to transmit a UDP message.
static void qc_fragment_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We are finished with a fragment in the message queue.
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:741
struct UDP_MessageWrapper * ipv4_queue_head
Head of messages in IPv4 queue.
static void udp_select_read(struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
Read and process a message from the given socket.
void GNUNET_CONTAINER_heap_iterate(const struct GNUNET_CONTAINER_Heap *heap, GNUNET_CONTAINER_HeapIterator iterator, void *iterator_cls)
Iterate over all entries in the heap.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON
Message send by a peer to notify the other to keep the session alive.
GNUNET_TRANSPORT_CheckAddress check_address
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
GNUNET_TRANSPORT_SessionState
Possible states of a session in a plugin.
GNUNET_TRANSPORT_TransmitContinuation cont
Function to call upon completion of the transmission.
struct UDP_FragmentationContext * frag_ctx
Context for dealing with fragments.
int GNUNET_NETWORK_fdset_isset(const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc)
Check whether a socket is part of the fd set.
Definition: network.c:1017
static int send_session_info_iter(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Return information about the given session to the monitor callback.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
ssize_t GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length, struct sockaddr *src_addr, socklen_t *addrlen)
Read data from a socket (always non-blocking).
Definition: network.c:742
void GNUNET_FRAGMENT_context_destroy(struct GNUNET_FRAGMENT_Context *fc, struct GNUNET_TIME_Relative *msg_delay, struct GNUNET_TIME_Relative *ack_delay)
Destroy the given fragmentation context (stop calling &#39;proc&#39;, free resources).
struct Plugin * plugin
Reference to master plugin struct.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
static void read_process_fragment(struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, const union UdpAddress *udp_addr, size_t udp_addr_len, enum GNUNET_NetworkType network_type)
We received a fragment, process it.
static char * address
GNS address for this phone.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define UDP_MAX_MESSAGES_IN_DEFRAG
Number of messages we can defragment in parallel.
static unsigned int setup_sockets(struct Plugin *plugin, const struct sockaddr_in6 *bind_v6, const struct sockaddr_in *bind_v4)
Setup the UDP sockets (for IPv4 and IPv6) for the plugin.
#define LOG(kind,...)
void(* QueueContinuation)(void *cls, struct UDP_MessageWrapper *udpw, int result)
Function called when a message is removed from the transmission queue.
struct GNUNET_FRAGMENT_Context * frag
Handle for fragmentation.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:548
#define GNUNET_HELLO_address_free(addr)
Free an address.
size_t msg_size
Size of UDP message to send, including UDP-specific overhead.
void * libgnunet_plugin_transport_udp_init(void *cls)
The exported method.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_STRINGS_to_address_ip(const char *addr, uint16_t addrlen, struct sockaddr_storage *r_buf)
Tries to convert addr string to an IP (v4 or v6) address.
Definition: strings.c:1327
void * sic_cls
Closure for sic.
#define GNUNET_malloc(size)
Wrapper around malloc.
int enable_ipv6
Is IPv6 enabled: GNUNET_YES or GNUNET_NO.
static struct GNUNET_FS_DownloadContext * dc
struct GNUNET_PeerIdentity sender
Who&#39;s message(s) are we defragmenting here? Only initialized once we succeeded and have_sender is set...
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
struct GNUNET_TIME_Absolute timeout
Message timeout.
static struct GNUNET_SCHEDULER_Task * t6
Task for IPv6 socket.
static int check_port(const struct Plugin *plugin, uint16_t in_port)
Check if the given port is plausible (must be either our listen port or our advertised port)...
GNUNET_TRANSPORT_GetNetworkTypeForAddress get_network_for_address
Function to obtain the network type for an address.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:900
Category of last resort.
Definition: gnunet_nt_lib.h:39
struct GNUNET_TIME_Absolute next_frag_time
Transmission time for the next fragment.
static void reschedule_session_timeout(struct GNUNET_ATS_Session *s)
Increment session timeout due to activity.
static int ipv6
Option -6: IPv6 requested.
Definition: gnunet-vpn.c:66
struct GNUNET_PeerIdentity sender
What is the identity of the sender.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
High-quality operations are desired.