GNUnet  0.20.0
plugin_transport_tcp.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2002--2015 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  */
25 #include "platform.h"
26 #include "gnunet_hello_lib.h"
27 #include "gnunet_constants.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_nat_service.h"
30 #include "gnunet_protocols.h"
32 #include "gnunet_signatures.h"
36 #include "transport.h"
37 
38 #define LOG(kind, ...) GNUNET_log_from (kind, "transport-tcp", __VA_ARGS__)
39 
40 #define PLUGIN_NAME "tcp"
41 
46 #define NAT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
47 
53 
58 
63 
68 
73 
78 
79 
85 void
87 
88 
99 typedef size_t (*GNUNET_CONNECTION_TransmitReadyNotify) (void *cls,
100  size_t size,
101  void *buf);
102 
107 {
111  uid_t uid;
112 
116  gid_t gid;
117 };
118 
119 
129  void *cls,
130  struct GNUNET_SERVER_Client *client);
131 
132 
141  void *cls,
142  struct GNUNET_SERVER_Client *client);
143 
144 
156  void *cls,
157  const struct GNUNET_CONNECTION_Credentials *ucred,
158  const struct sockaddr *addr,
159  socklen_t addrlen);
160 
173 typedef void (*GNUNET_CONNECTION_Receiver) (void *cls,
174  const void *buf,
175  size_t available,
176  const struct sockaddr *addr,
177  socklen_t addrlen,
178  int errCode);
179 
180 
188 void
190 
191 
199 typedef void *(*GNUNET_SERVER_MstCreateCallback) (
200  void *cls,
201  struct GNUNET_SERVER_Client *client);
202 
203 
210 typedef void (*GNUNET_SERVER_MstDestroyCallback) (void *cls, void *mst);
211 
229  void *cls,
230  void *mst,
231  struct GNUNET_SERVER_Client *client,
232  const char *buf,
233  size_t size,
234  int purge,
235  int one_shot);
245  void *cls,
246  struct GNUNET_SERVER_Client *client,
247  const struct GNUNET_MessageHeader *message);
248 
254 {
259 
264 
268  uint16_t type;
269 
276  uint16_t expected_size;
277 };
278 
279 
284 {
290 
297 
303 };
304 
305 
314 void
316 
325 void *
327  size_t size);
328 
329 
343  void *cls,
344  void *client,
345  const struct GNUNET_MessageHeader *message);
346 
347 
357  void *cb_cls);
358 
375 int
377  void *client_identity,
378  const char *buf,
379  size_t size,
380  int purge,
381  int one_shot);
382 
383 
389 void
391 
392 
401 void
403  void *ptr,
404  size_t size);
405 
413 #define GNUNET_SERVER_client_get_user_context(client, type) \
414  (type *) GNUNET_SERVER_client_get_user_context_ (client, sizeof(type))
415 
422 #define GNUNET_SERVER_client_set_user_context(client, value) \
423  GNUNET_SERVER_client_set_user_context_ (client, value, sizeof(*value))
424 
425 
443  struct GNUNET_SERVER_Client *client,
444  size_t size,
447  void *callback_cls);
448 
454 void
456  struct GNUNET_SERVER_TransmitHandle *th);
457 
458 
466 void
468 
469 
478 void
480 
481 
490 typedef void (*LEGACY_SERVICE_Main) (
491  void *cls,
492  struct GNUNET_SERVER_Handle *server,
493  const struct GNUNET_CONFIGURATION_Handle *cfg);
494 
495 
502 void
504 
522  struct GNUNET_SERVER_Client *client,
523  size_t size,
526  void *callback_cls);
527 
528 
540 struct GNUNET_SERVER_Client *
543 
544 
550 void
552 
558 void
560 
561 
562 #include "tcp_connection_legacy.c"
563 #include "tcp_server_mst_legacy.c"
564 #include "tcp_server_legacy.c"
565 #include "tcp_service_legacy.c"
566 
568 
573 {
578 
583 };
584 
590 {
595 
600 };
602 
607 {
612 
617 
622 
627 
632 
636  struct Plugin *plugin;
637 };
638 
643 {
648 
653 
658 };
659 
661 
666 {
672 
677 
682 };
683 
688 {
694 
698  struct in6_addr ipv6_addr GNUNET_PACKED;
699 
704 };
706 
710 struct Plugin;
711 
716 struct PendingMessage
717 {
721  struct PendingMessage *next;
722 
726  struct PendingMessage *prev;
727 
731  const char *msg;
732 
739 
744 
749 
755  size_t message_size;
756 };
757 
761 struct GNUNET_ATS_Session
762 {
768 
772  struct Plugin *plugin;
773 
778 
783 
789 
795 
800 
805 
810 
815 
820 
826 
832 
836  unsigned long long bytes_in_queue;
837 
841  unsigned int msgs_in_queue;
842 
847 
852 
856  int is_nat;
857 };
858 
859 
865 {
869  struct PrettyPrinterContext *next;
870 
874  struct PrettyPrinterContext *prev;
875 
879  struct Plugin *plugin;
880 
885 
890 
895 
899  void *asc_cls;
900 
904  int ipv6;
905 
909  uint32_t options;
910 
914  uint16_t port;
915 };
916 
917 
921 struct Plugin
922 {
927 
932 
936  struct GNUNET_NAT_Handle *nat;
937 
942 
947 
952 
958 
963 
968 
973 
978 
982  void *sic_cls;
983 
988 
993 
998 
1002  struct WelcomeMessage my_welcome;
1003 
1007  unsigned long long max_connections;
1008 
1012  unsigned long long cur_connections;
1013 
1017  uint32_t myoptions;
1018 
1022  uint16_t open_port;
1023 
1028  uint16_t adv_port;
1029 };
1030 
1031 
1052 static int
1054  const struct GNUNET_CONFIGURATION_Handle *cfg,
1055  struct sockaddr ***addrs,
1056  socklen_t **addr_lens)
1057 {
1058  int disablev6;
1059  struct GNUNET_NETWORK_Handle *desc;
1060  unsigned long long port;
1061  char *unixpath;
1062  struct addrinfo hints;
1063  struct addrinfo *res;
1064  struct addrinfo *pos;
1065  struct addrinfo *next;
1066  unsigned int i;
1067  int resi;
1068  int ret;
1069  int abstract;
1070  struct sockaddr **saddrs;
1071  socklen_t *saddrlens;
1072  char *hostname;
1073 
1074  *addrs = NULL;
1075  *addr_lens = NULL;
1076  desc = NULL;
1077  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
1078  {
1079  if (GNUNET_SYSERR ==
1081  service_name,
1082  "DISABLEV6")))
1083  return GNUNET_SYSERR;
1084  }
1085  else
1086  disablev6 = GNUNET_NO;
1087 
1088  if (! disablev6)
1089  {
1090  /* probe IPv6 support */
1091  desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
1092  if (NULL == desc)
1093  {
1094  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1095  (EACCES == errno))
1096  {
1098  return GNUNET_SYSERR;
1099  }
1101  _ (
1102  "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
1103  service_name,
1104  strerror (errno));
1105  disablev6 = GNUNET_YES;
1106  }
1107  else
1108  {
1110  desc = NULL;
1111  }
1112  }
1113 
1114  port = 0;
1116  {
1118  service_name,
1119  "PORT",
1120  &port))
1121  {
1123  _ ("Require valid port number for service `%s' in configuration!\n"),
1124  service_name);
1125  }
1126  if (port > 65535)
1127  {
1129  _ ("Require valid port number for service `%s' in configuration!\n"),
1130  service_name);
1131  return GNUNET_SYSERR;
1132  }
1133  }
1134 
1136  {
1139  service_name,
1140  "BINDTO",
1141  &hostname));
1142  }
1143  else
1144  hostname = NULL;
1145 
1146  unixpath = NULL;
1147  abstract = GNUNET_NO;
1148 #ifdef AF_UNIX
1149  if ((GNUNET_YES ==
1152  service_name,
1153  "UNIXPATH",
1154  &unixpath)) &&
1155  (0 < strlen (unixpath)))
1156  {
1157  /* probe UNIX support */
1158  struct sockaddr_un s_un;
1159 
1160  if (strlen (unixpath) >= sizeof(s_un.sun_path))
1161  {
1163  _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
1164  unixpath,
1165  (unsigned long long) sizeof(s_un.sun_path));
1166  unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1167  LOG (GNUNET_ERROR_TYPE_INFO, _ ("Using `%s' instead\n"), unixpath);
1168  }
1169 #ifdef __linux__
1171  "TESTING",
1172  "USE_ABSTRACT_SOCKETS");
1173  if (GNUNET_SYSERR == abstract)
1174  abstract = GNUNET_NO;
1175 #endif
1176  if ((GNUNET_YES != abstract) &&
1179  }
1180  if (NULL != unixpath)
1181  {
1182  desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
1183  if (NULL == desc)
1184  {
1185  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1186  (EACCES == errno))
1187  {
1190  GNUNET_free (unixpath);
1191  return GNUNET_SYSERR;
1192  }
1194  _ (
1195  "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1196  service_name,
1197  strerror (errno));
1198  GNUNET_free (unixpath);
1199  unixpath = NULL;
1200  }
1201  else
1202  {
1204  desc = NULL;
1205  }
1206  }
1207 #endif
1208 
1209  if ((0 == port) && (NULL == unixpath))
1210  {
1212  _ (
1213  "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1214  service_name);
1216  return GNUNET_SYSERR;
1217  }
1218  if (0 == port)
1219  {
1220  saddrs = GNUNET_malloc (2 * sizeof(struct sockaddr *));
1221  saddrlens = GNUNET_malloc (2 * sizeof(socklen_t));
1222  add_unixpath (saddrs, saddrlens, unixpath, abstract);
1223  GNUNET_free (unixpath);
1225  *addrs = saddrs;
1226  *addr_lens = saddrlens;
1227  return 1;
1228  }
1229 
1230  if (NULL != hostname)
1231  {
1233  "Resolving `%s' since that is where `%s' will bind to.\n",
1234  hostname,
1235  service_name);
1236  memset (&hints, 0, sizeof(struct addrinfo));
1237  if (disablev6)
1238  hints.ai_family = AF_INET;
1239  hints.ai_protocol = IPPROTO_TCP;
1240  if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1241  (NULL == res))
1242  {
1244  _ ("Failed to resolve `%s': %s\n"),
1245  hostname,
1246  gai_strerror (ret));
1248  GNUNET_free (unixpath);
1249  return GNUNET_SYSERR;
1250  }
1251  next = res;
1252  i = 0;
1253  while (NULL != (pos = next))
1254  {
1255  next = pos->ai_next;
1256  if ((disablev6) && (pos->ai_family == AF_INET6))
1257  continue;
1258  i++;
1259  }
1260  if (0 == i)
1261  {
1263  _ ("Failed to find %saddress for `%s'.\n"),
1264  disablev6 ? "IPv4 " : "",
1265  hostname);
1266  freeaddrinfo (res);
1268  GNUNET_free (unixpath);
1269  return GNUNET_SYSERR;
1270  }
1271  resi = i;
1272  if (NULL != unixpath)
1273  resi++;
1274  saddrs = GNUNET_malloc ((resi + 1) * sizeof(struct sockaddr *));
1275  saddrlens = GNUNET_malloc ((resi + 1) * sizeof(socklen_t));
1276  i = 0;
1277  if (NULL != unixpath)
1278  {
1279  add_unixpath (saddrs, saddrlens, unixpath, abstract);
1280  i++;
1281  }
1282  next = res;
1283  while (NULL != (pos = next))
1284  {
1285  next = pos->ai_next;
1286  if ((disablev6) && (AF_INET6 == pos->ai_family))
1287  continue;
1288  if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1289  continue; /* not TCP */
1290  if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1291  continue; /* huh? */
1293  "Service `%s' will bind to `%s'\n",
1294  service_name,
1295  GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1296  if (AF_INET == pos->ai_family)
1297  {
1298  GNUNET_assert (sizeof(struct sockaddr_in) == pos->ai_addrlen);
1299  saddrlens[i] = pos->ai_addrlen;
1300  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1301  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1302  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1303  }
1304  else
1305  {
1306  GNUNET_assert (AF_INET6 == pos->ai_family);
1307  GNUNET_assert (sizeof(struct sockaddr_in6) == pos->ai_addrlen);
1308  saddrlens[i] = pos->ai_addrlen;
1309  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1310  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1311  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1312  }
1313  i++;
1314  }
1316  freeaddrinfo (res);
1317  resi = i;
1318  }
1319  else
1320  {
1321  /* will bind against everything, just set port */
1322  if (disablev6)
1323  {
1324  /* V4-only */
1325  resi = 1;
1326  if (NULL != unixpath)
1327  resi++;
1328  i = 0;
1329  saddrs = GNUNET_malloc ((resi + 1) * sizeof(struct sockaddr *));
1330  saddrlens = GNUNET_malloc ((resi + 1) * sizeof(socklen_t));
1331  if (NULL != unixpath)
1332  {
1333  add_unixpath (saddrs, saddrlens, unixpath, abstract);
1334  i++;
1335  }
1336  saddrlens[i] = sizeof(struct sockaddr_in);
1337  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1338 #if HAVE_SOCKADDR_IN_SIN_LEN
1339  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1340 #endif
1341  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1342  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1343  }
1344  else
1345  {
1346  /* dual stack */
1347  resi = 2;
1348  if (NULL != unixpath)
1349  resi++;
1350  saddrs = GNUNET_malloc ((resi + 1) * sizeof(struct sockaddr *));
1351  saddrlens = GNUNET_malloc ((resi + 1) * sizeof(socklen_t));
1352  i = 0;
1353  if (NULL != unixpath)
1354  {
1355  add_unixpath (saddrs, saddrlens, unixpath, abstract);
1356  i++;
1357  }
1358  saddrlens[i] = sizeof(struct sockaddr_in6);
1359  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1360 #if HAVE_SOCKADDR_IN_SIN_LEN
1361  ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1362 #endif
1363  ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1364  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1365  i++;
1366  saddrlens[i] = sizeof(struct sockaddr_in);
1367  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1368 #if HAVE_SOCKADDR_IN_SIN_LEN
1369  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1370 #endif
1371  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1372  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1373  }
1374  }
1375  GNUNET_free (unixpath);
1376  *addrs = saddrs;
1377  *addr_lens = saddrlens;
1378  return resi;
1379 }
1380 
1381 
1382 /* end ancient copy-and-paste */
1383 
1384 
1393 static void
1395  struct GNUNET_ATS_Session *session,
1397 {
1399 
1400  if (NULL == plugin->sic)
1401  return;
1402  memset (&info, 0, sizeof(info));
1403  info.state = state;
1404  info.is_inbound =
1407  info.num_msg_pending = session->msgs_in_queue;
1408  info.num_bytes_pending = session->bytes_in_queue;
1409  if (NULL != session->receive_delay_task)
1410  info.receive_delay = session->receive_delay;
1411  info.session_timeout = session->timeout;
1412  info.address = session->address;
1413  plugin->sic (plugin->sic_cls, session, &info);
1414 }
1415 
1416 
1429 static void
1431  void **app_ctx,
1432  int add_remove,
1434  const struct sockaddr *addr,
1435  socklen_t addrlen)
1436 {
1437  struct Plugin *plugin = cls;
1438  struct GNUNET_HELLO_Address *address;
1439  struct IPv4TcpAddress t4;
1440  struct IPv6TcpAddress t6;
1441  void *arg;
1442  size_t args;
1443 
1444  (void) app_ctx;
1446  "NAT notification to %s address `%s'\n",
1447  (GNUNET_YES == add_remove) ? "add" : "remove",
1448  GNUNET_a2s (addr, addrlen));
1449  /* convert 'addr' to our internal format */
1450  switch (addr->sa_family)
1451  {
1452  case AF_INET:
1453  GNUNET_assert (addrlen == sizeof(struct sockaddr_in));
1454  memset (&t4, 0, sizeof(t4));
1455  t4.options = htonl (plugin->myoptions);
1456  t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1457  t4.t4_port = ((struct sockaddr_in *) addr)->sin_port;
1458  arg = &t4;
1459  args = sizeof(t4);
1460  break;
1461 
1462  case AF_INET6:
1463  if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
1464  {
1465  /* skip link local, we don't allow them in
1466  #tcp_plugin_check_address() */
1467  return;
1468  }
1469  GNUNET_assert (addrlen == sizeof(struct sockaddr_in6));
1470  memset (&t6, 0, sizeof(t6));
1471  GNUNET_memcpy (&t6.ipv6_addr,
1472  &((struct sockaddr_in6 *) addr)->sin6_addr,
1473  sizeof(struct in6_addr));
1474  t6.options = htonl (plugin->myoptions);
1475  t6.t6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
1476  arg = &t6;
1477  args = sizeof(t6);
1478  break;
1479 
1480  default:
1481  GNUNET_break (0);
1482  return;
1483  }
1484  /* modify our published address list */
1485  GNUNET_assert ((args == sizeof(struct IPv4TcpAddress)) ||
1486  (args == sizeof(struct IPv6TcpAddress)));
1487  /* TODO: use 'ac' here in the future... */
1488  address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1489  PLUGIN_NAME,
1490  arg,
1491  args,
1493  plugin->env->notify_address (plugin->env->cls, add_remove, address);
1495 }
1496 
1497 
1509 static const char *
1510 tcp_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
1511 {
1512  static char rbuf[INET6_ADDRSTRLEN + 12];
1513  char buf[INET6_ADDRSTRLEN];
1514  const void *sb;
1515  struct in_addr a4;
1516  struct in6_addr a6;
1517  const struct IPv4TcpAddress *t4;
1518  const struct IPv6TcpAddress *t6;
1519  int af;
1520  uint16_t port;
1521  uint32_t options;
1522 
1523  switch (addrlen)
1524  {
1525  case sizeof(struct IPv6TcpAddress):
1526  t6 = addr;
1527  af = AF_INET6;
1528  port = ntohs (t6->t6_port);
1529  options = ntohl (t6->options);
1530  GNUNET_memcpy (&a6, &t6->ipv6_addr, sizeof(a6));
1531  sb = &a6;
1532  break;
1533 
1534  case sizeof(struct IPv4TcpAddress):
1535  t4 = addr;
1536  af = AF_INET;
1537  port = ntohs (t4->t4_port);
1538  options = ntohl (t4->options);
1539  GNUNET_memcpy (&a4, &t4->ipv4_addr, sizeof(a4));
1540  sb = &a4;
1541  break;
1542 
1543  default:
1544  LOG (GNUNET_ERROR_TYPE_WARNING,
1545  _ ("Unexpected address length: %u bytes\n"),
1546  (unsigned int) addrlen);
1547  return NULL;
1548  }
1549  if (NULL == inet_ntop (af, sb, buf, INET6_ADDRSTRLEN))
1550  {
1552  return NULL;
1553  }
1554  GNUNET_snprintf (rbuf,
1555  sizeof(rbuf),
1556  (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u",
1557  PLUGIN_NAME,
1558  options,
1559  buf,
1560  port);
1561  return rbuf;
1562 }
1563 
1564 
1577 static int
1579  const char *addr,
1580  uint16_t addrlen,
1581  void **buf,
1582  size_t *added)
1583 {
1584  struct sockaddr_storage socket_address;
1585  char *address;
1586  char *plugin;
1587  char *optionstr;
1588  uint32_t options;
1589 
1590  /* Format tcp.options.address:port */
1591  address = NULL;
1592  plugin = NULL;
1593  optionstr = NULL;
1594  if ((NULL == addr) || (0 == addrlen))
1595  {
1596  GNUNET_break (0);
1597  return GNUNET_SYSERR;
1598  }
1599  if ('\0' != addr[addrlen - 1])
1600  {
1601  GNUNET_break (0);
1602  return GNUNET_SYSERR;
1603  }
1604  if (strlen (addr) != addrlen - 1)
1605  {
1606  GNUNET_break (0);
1607  return GNUNET_SYSERR;
1608  }
1609  plugin = GNUNET_strdup (addr);
1610  optionstr = strchr (plugin, '.');
1611  if (NULL == optionstr)
1612  {
1613  GNUNET_break (0);
1614  GNUNET_free (plugin);
1615  return GNUNET_SYSERR;
1616  }
1617  optionstr[0] = '\0';
1618  optionstr++;
1619  options = atol (optionstr);
1620  address = strchr (optionstr, '.');
1621  if (NULL == address)
1622  {
1623  GNUNET_break (0);
1624  GNUNET_free (plugin);
1625  return GNUNET_SYSERR;
1626  }
1627  address[0] = '\0';
1628  address++;
1629 
1630  if (GNUNET_OK !=
1631  GNUNET_STRINGS_to_address_ip (address, strlen (address), &socket_address))
1632  {
1633  GNUNET_break (0);
1634  GNUNET_free (plugin);
1635  return GNUNET_SYSERR;
1636  }
1637 
1638  GNUNET_free (plugin);
1639  switch (socket_address.ss_family)
1640  {
1641  case AF_INET: {
1642  struct IPv4TcpAddress *t4;
1643  struct sockaddr_in *in4 = (struct sockaddr_in *) &socket_address;
1644  t4 = GNUNET_new (struct IPv4TcpAddress);
1645  t4->options = htonl (options);
1646  t4->ipv4_addr = in4->sin_addr.s_addr;
1647  t4->t4_port = in4->sin_port;
1648  *buf = t4;
1649  *added = sizeof(struct IPv4TcpAddress);
1650  return GNUNET_OK;
1651  }
1652 
1653  case AF_INET6: {
1654  struct IPv6TcpAddress *t6;
1655  struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &socket_address;
1656  t6 = GNUNET_new (struct IPv6TcpAddress);
1657  t6->options = htonl (options);
1658  t6->ipv6_addr = in6->sin6_addr;
1659  t6->t6_port = in6->sin6_port;
1660  *buf = t6;
1661  *added = sizeof(struct IPv6TcpAddress);
1662  return GNUNET_OK;
1663  }
1664 
1665  default:
1666  return GNUNET_SYSERR;
1667  }
1668 }
1669 
1670 
1681 static struct GNUNET_ATS_Session *
1683  struct GNUNET_SERVER_Client *client)
1684 {
1686  struct GNUNET_ATS_Session);
1687 }
1688 
1689 
1699 static int
1701 {
1702  struct Plugin *plugin = cls;
1703  struct PendingMessage *pm;
1704 
1706  "Disconnecting session of peer `%s' address `%s'\n",
1707  GNUNET_i2s (&session->target),
1709  session->address->address,
1710  session->address->address_length));
1711 
1712  if (NULL != session->timeout_task)
1713  {
1715  session->timeout_task = NULL;
1717  }
1718 
1720  &session->target,
1721  session))
1722  {
1723  GNUNET_STATISTICS_update (session->plugin->env->stats,
1724  gettext_noop ("# TCP sessions active"),
1725  -1,
1726  GNUNET_NO);
1727  }
1728  else
1729  {
1732  &session->target,
1733  session));
1734  }
1735  if (NULL != session->client)
1737 
1738  /* clean up state */
1739  if (NULL != session->transmit_handle)
1740  {
1742  session->transmit_handle = NULL;
1743  }
1744  session->plugin->env->session_end (session->plugin->env->cls,
1745  session->address,
1746  session);
1747 
1748  if (NULL != session->nat_connection_timeout)
1749  {
1751  session->nat_connection_timeout = NULL;
1752  }
1753 
1754  while (NULL != (pm = session->pending_messages_head))
1755  {
1757  (NULL != pm->transmit_cont)
1758  ? "Could not deliver message to `%s' at %s.\n"
1759  : "Could not deliver message to `%s' at %s, notifying.\n",
1760  GNUNET_i2s (&session->target),
1762  session->address->address,
1763  session->address->address_length));
1764  GNUNET_STATISTICS_update (session->plugin->env->stats,
1765  gettext_noop ("# bytes currently in TCP buffers"),
1766  -(int64_t) pm->message_size,
1767  GNUNET_NO);
1768  GNUNET_STATISTICS_update (session->plugin->env->stats,
1769  gettext_noop (
1770  "# bytes discarded by TCP (disconnect)"),
1771  pm->message_size,
1772  GNUNET_NO);
1774  session->pending_messages_tail,
1775  pm);
1776  GNUNET_assert (0 < session->msgs_in_queue);
1777  session->msgs_in_queue--;
1778  GNUNET_assert (pm->message_size <= session->bytes_in_queue);
1779  session->bytes_in_queue -= pm->message_size;
1780  if (NULL != pm->transmit_cont)
1781  pm->transmit_cont (pm->transmit_cont_cls,
1782  &session->target,
1783  GNUNET_SYSERR,
1784  pm->message_size,
1785  0);
1786  GNUNET_free (pm);
1787  }
1788  GNUNET_assert (0 == session->msgs_in_queue);
1789  GNUNET_assert (0 == session->bytes_in_queue);
1791 
1792  if (NULL != session->receive_delay_task)
1793  {
1795  session->receive_delay_task = NULL;
1796  }
1797  if (NULL != session->client)
1798  {
1800  session->client = NULL;
1801  }
1803  GNUNET_assert (NULL == session->transmit_handle);
1804  GNUNET_free (session);
1805  return GNUNET_OK;
1806 }
1807 
1808 
1817 static unsigned int
1819 {
1820  return 3;
1821 }
1822 
1823 
1829 static void
1830 session_timeout (void *cls)
1831 {
1832  struct GNUNET_ATS_Session *s = cls;
1833  struct GNUNET_TIME_Relative left;
1834 
1835  s->timeout_task = NULL;
1837  if (0 != left.rel_value_us)
1838  {
1839  /* not actually our turn yet, but let's at least update
1840  the monitor, it may think we're about to die ... */
1843  return;
1844  }
1846  "Session %p was idle for %s, disconnecting\n",
1847  s,
1850  GNUNET_YES));
1851  /* call session destroy function */
1853 }
1854 
1855 
1861 static void
1863 {
1864  GNUNET_assert (NULL != s->timeout_task);
1865  s->timeout =
1867 }
1868 
1869 
1882 static struct GNUNET_ATS_Session *
1884  const struct GNUNET_HELLO_Address *address,
1886  struct GNUNET_SERVER_Client *client,
1887  int is_nat)
1888 {
1889  struct GNUNET_ATS_Session *session;
1890  struct PendingMessage *pm;
1891 
1892  if (GNUNET_YES != is_nat)
1893  GNUNET_assert (NULL != client);
1894  else
1895  GNUNET_assert (NULL == client);
1896 
1898  "Creating new session for peer `%s' at address %s\n",
1899  GNUNET_i2s (&address->peer),
1901  address->address,
1902  address->address_length));
1903  session = GNUNET_new (struct GNUNET_ATS_Session);
1905  session->plugin = plugin;
1906  session->is_nat = is_nat;
1907  if (NULL != client)
1908  {
1909  session->client = client;
1911  }
1913  session->target = address->peer;
1914  session->expecting_welcome = GNUNET_YES;
1915  session->scope = scope;
1916  pm = GNUNET_malloc (sizeof(struct PendingMessage)
1917  + sizeof(struct WelcomeMessage));
1918  pm->msg = (const char *) &pm[1];
1919  pm->message_size = sizeof(struct WelcomeMessage);
1920  GNUNET_memcpy (&pm[1], &plugin->my_welcome, sizeof(struct WelcomeMessage));
1921  pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1922  GNUNET_STATISTICS_update (plugin->env->stats,
1923  gettext_noop ("# bytes currently in TCP buffers"),
1924  pm->message_size,
1925  GNUNET_NO);
1927  session->pending_messages_tail,
1928  pm);
1929  session->msgs_in_queue++;
1930  session->bytes_in_queue += pm->message_size;
1931  session->timeout =
1933  session->timeout_task =
1935  &session_timeout,
1936  session);
1938  if (GNUNET_YES != is_nat)
1939  {
1940  GNUNET_STATISTICS_update (plugin->env->stats,
1941  gettext_noop ("# TCP sessions active"),
1942  1,
1943  GNUNET_NO);
1945  }
1946  else
1947  {
1948  notify_session_monitor (session->plugin,
1949  session,
1951  }
1952  return session;
1953 }
1954 
1955 
1962 static void
1964 
1965 
1977 static size_t
1978 do_transmit (void *cls, size_t size, void *buf)
1979 {
1980  struct GNUNET_ATS_Session *session = cls;
1981  struct GNUNET_PeerIdentity pid;
1982  struct Plugin *plugin;
1983  struct PendingMessage *pos;
1984  struct PendingMessage *hd;
1985  struct PendingMessage *tl;
1986  struct GNUNET_TIME_Absolute now;
1987  char *cbuf;
1988  size_t ret;
1989 
1990  session->transmit_handle = NULL;
1991  plugin = session->plugin;
1992  if (NULL == buf)
1993  {
1995  "Timeout trying to transmit to peer `%s', discarding message queue.\n",
1996  GNUNET_i2s (&session->target));
1997  /* timeout; cancel all messages that have already expired */
1998  hd = NULL;
1999  tl = NULL;
2000  ret = 0;
2001  now = GNUNET_TIME_absolute_get ();
2002  while ((NULL != (pos = session->pending_messages_head)) &&
2003  (pos->timeout.abs_value_us <= now.abs_value_us))
2004  {
2006  session->pending_messages_tail,
2007  pos);
2008  GNUNET_assert (0 < session->msgs_in_queue);
2009  session->msgs_in_queue--;
2010  GNUNET_assert (pos->message_size <= session->bytes_in_queue);
2011  session->bytes_in_queue -= pos->message_size;
2013  "Failed to transmit %lu byte message to `%s'.\n",
2014  (unsigned long) pos->message_size,
2015  GNUNET_i2s (&session->target));
2016  ret += pos->message_size;
2017  GNUNET_CONTAINER_DLL_insert_after (hd, tl, tl, pos);
2018  }
2019  /* do this call before callbacks (so that if callbacks destroy
2020  * session, they have a chance to cancel actions done by this
2021  * call) */
2022  process_pending_messages (session);
2023  pid = session->target;
2024  /* no do callbacks and do not use session again since
2025  * the callbacks may abort the session */
2026  while (NULL != (pos = hd))
2027  {
2028  GNUNET_CONTAINER_DLL_remove (hd, tl, pos);
2029  if (NULL != pos->transmit_cont)
2030  pos->transmit_cont (pos->transmit_cont_cls,
2031  &pid,
2032  GNUNET_SYSERR,
2033  pos->message_size,
2034  0);
2035  GNUNET_free (pos);
2036  }
2037  GNUNET_STATISTICS_update (plugin->env->stats,
2038  gettext_noop ("# bytes currently in TCP buffers"),
2039  -(int64_t) ret,
2040  GNUNET_NO);
2041  GNUNET_STATISTICS_update (plugin->env->stats,
2042  gettext_noop (
2043  "# bytes discarded by TCP (timeout)"),
2044  ret,
2045  GNUNET_NO);
2046  if (0 < ret)
2047  notify_session_monitor (session->plugin,
2048  session,
2050  return 0;
2051  }
2052  /* copy all pending messages that would fit */
2053  ret = 0;
2054  cbuf = buf;
2055  hd = NULL;
2056  tl = NULL;
2057  while (NULL != (pos = session->pending_messages_head))
2058  {
2059  if (ret + pos->message_size > size)
2060  break;
2062  session->pending_messages_tail,
2063  pos);
2064  GNUNET_assert (0 < session->msgs_in_queue);
2065  session->msgs_in_queue--;
2066  GNUNET_assert (pos->message_size <= session->bytes_in_queue);
2067  session->bytes_in_queue -= pos->message_size;
2068  GNUNET_assert (size >= pos->message_size);
2070  "Transmitting message of type %u size %lu to peer %s at %s\n",
2071  ntohs (((struct GNUNET_MessageHeader *) pos->msg)->type),
2072  (unsigned long) pos->message_size,
2073  GNUNET_i2s (&session->target),
2075  session->address->address,
2076  session->address->address_length));
2077  /* FIXME: this GNUNET_memcpy can be up to 7% of our total runtime */
2078  GNUNET_memcpy (cbuf, pos->msg, pos->message_size);
2079  cbuf += pos->message_size;
2080  ret += pos->message_size;
2081  size -= pos->message_size;
2082  GNUNET_CONTAINER_DLL_insert_tail (hd, tl, pos);
2083  }
2085  /* schedule 'continuation' before callbacks so that callbacks that
2086  * cancel everything don't cause us to use a session that no longer
2087  * exists... */
2088  process_pending_messages (session);
2090  pid = session->target;
2091  /* we'll now call callbacks that may cancel the session; hence
2092  * we should not use 'session' after this point */
2093  while (NULL != (pos = hd))
2094  {
2095  GNUNET_CONTAINER_DLL_remove (hd, tl, pos);
2096  if (NULL != pos->transmit_cont)
2097  pos->transmit_cont (pos->transmit_cont_cls,
2098  &pid,
2099  GNUNET_OK,
2100  pos->message_size,
2101  pos->message_size); /* FIXME: include TCP overhead */
2102  GNUNET_free (pos);
2103  }
2104  GNUNET_assert (NULL == hd);
2105  GNUNET_assert (NULL == tl);
2106  GNUNET_STATISTICS_update (plugin->env->stats,
2107  gettext_noop ("# bytes currently in TCP buffers"),
2108  -(int64_t) ret,
2109  GNUNET_NO);
2110  GNUNET_STATISTICS_update (plugin->env->stats,
2111  gettext_noop ("# bytes transmitted via TCP"),
2112  ret,
2113  GNUNET_NO);
2114  return ret;
2115 }
2116 
2117 
2124 static void
2126 {
2127  struct PendingMessage *pm;
2128 
2129  GNUNET_assert (NULL != session->client);
2130  if (NULL != session->transmit_handle)
2131  return;
2132  if (NULL == (pm = session->pending_messages_head))
2133  return;
2134 
2135  session->transmit_handle =
2137  pm->message_size,
2139  pm->timeout),
2140  &do_transmit,
2141  session);
2142 }
2143 
2144 
2172 static ssize_t
2173 tcp_plugin_send (void *cls,
2174  struct GNUNET_ATS_Session *session,
2175  const char *msgbuf,
2176  size_t msgbuf_size,
2177  unsigned int priority,
2178  struct GNUNET_TIME_Relative to,
2180  void *cont_cls)
2181 {
2182  struct Plugin *plugin = cls;
2183  struct PendingMessage *pm;
2184 
2185  /* create new message entry */
2186  pm = GNUNET_malloc (sizeof(struct PendingMessage) + msgbuf_size);
2187  pm->msg = (const char *) &pm[1];
2188  GNUNET_memcpy (&pm[1], msgbuf, msgbuf_size);
2189  pm->message_size = msgbuf_size;
2190  pm->timeout = GNUNET_TIME_relative_to_absolute (to);
2191  pm->transmit_cont = cont;
2192  pm->transmit_cont_cls = cont_cls;
2193 
2195  "Asked to transmit %lu bytes to `%s', added message to list.\n",
2196  (unsigned long) msgbuf_size,
2197  GNUNET_i2s (&session->target));
2198 
2199  if (GNUNET_YES ==
2201  &session->target,
2202  session))
2203  {
2204  GNUNET_assert (NULL != session->client);
2207  GNUNET_STATISTICS_update (plugin->env->stats,
2208  gettext_noop ("# bytes currently in TCP buffers"),
2209  msgbuf_size,
2210  GNUNET_NO);
2211 
2212  /* append pm to pending_messages list */
2214  session->pending_messages_tail,
2215  pm);
2216  notify_session_monitor (session->plugin,
2217  session,
2219  session->msgs_in_queue++;
2220  session->bytes_in_queue += pm->message_size;
2221  process_pending_messages (session);
2222  return msgbuf_size;
2223  }
2224  if (GNUNET_YES ==
2226  &session->target,
2227  session))
2228  {
2230  "This NAT WAIT session for peer `%s' is not yet ready!\n",
2231  GNUNET_i2s (&session->target));
2232  GNUNET_STATISTICS_update (plugin->env->stats,
2233  gettext_noop ("# bytes currently in TCP buffers"),
2234  msgbuf_size,
2235  GNUNET_NO);
2236  /* append pm to pending_messages list */
2238  session->pending_messages_tail,
2239  pm);
2240  session->msgs_in_queue++;
2241  session->bytes_in_queue += pm->message_size;
2242  notify_session_monitor (session->plugin,
2243  session,
2245  return msgbuf_size;
2246  }
2247  LOG (GNUNET_ERROR_TYPE_ERROR, "Invalid session %p\n", session);
2248  if (NULL != cont)
2249  cont (cont_cls, &session->target, GNUNET_SYSERR, pm->message_size, 0);
2250  GNUNET_break (0);
2251  GNUNET_free (pm);
2252  return GNUNET_SYSERR; /* session does not exist here */
2253 }
2254 
2255 
2260 {
2265 
2270 };
2271 
2272 
2281 static int
2283  const struct GNUNET_PeerIdentity *key,
2284  void *value)
2285 {
2286  struct GNUNET_ATS_SessionItCtx *si_ctx = cls;
2287  struct GNUNET_ATS_Session *session = value;
2288 
2289  if (0 != GNUNET_HELLO_address_cmp (si_ctx->address, session->address))
2290  return GNUNET_YES;
2291  si_ctx->result = session;
2292  return GNUNET_NO;
2293 }
2294 
2295 
2301 static void
2303 {
2304  struct GNUNET_ATS_Session *session = cls;
2305 
2306  session->nat_connection_timeout = NULL;
2308  "NAT WAIT connection to `%4s' at `%s' could not be established, removing session\n",
2309  GNUNET_i2s (&session->target),
2311  session->address->address,
2312  session->address->address_length));
2313  tcp_plugin_disconnect_session (session->plugin, session);
2314 }
2315 
2316 
2326 static void
2328  const struct GNUNET_PeerIdentity *peer,
2329  struct GNUNET_ATS_Session *session)
2330 {
2331  reschedule_session_timeout (session);
2332 }
2333 
2334 
2341 static void
2342 delayed_done (void *cls)
2343 {
2344  struct GNUNET_ATS_Session *session = cls;
2345 
2346  session->receive_delay_task = NULL;
2347  reschedule_session_timeout (session);
2349 }
2350 
2351 
2362 static void
2364  const struct GNUNET_PeerIdentity *peer,
2365  struct GNUNET_ATS_Session *session,
2366  struct GNUNET_TIME_Relative delay)
2367 {
2368  if (NULL == session->receive_delay_task)
2369  return;
2371  "New inbound delay %s\n",
2375  session->receive_delay_task =
2377 }
2378 
2379 
2389 static struct GNUNET_ATS_Session *
2391 {
2392  struct Plugin *plugin = cls;
2393  struct GNUNET_ATS_Session *session = NULL;
2394  int af;
2395  const void *sb;
2396  size_t sbs;
2397  struct GNUNET_CONNECTION_Handle *sa;
2398  struct sockaddr_in a4;
2399  struct sockaddr_in6 a6;
2400  const struct IPv4TcpAddress *t4;
2401  const struct IPv6TcpAddress *t6;
2402  unsigned int options;
2403  enum GNUNET_NetworkType net_type;
2404  unsigned int is_natd = GNUNET_NO;
2405  size_t addrlen;
2406 
2407 #ifdef TCP_STEALTH
2408  struct GNUNET_NETWORK_Handle *s;
2409 #endif
2410 
2411  addrlen = address->address_length;
2413  "Trying to get session for `%s' address of peer `%s'\n",
2415  address->address,
2416  address->address_length),
2417  GNUNET_i2s (&address->peer));
2418 
2421  {
2422  GNUNET_break (0);
2423  return NULL;
2424  }
2425 
2426  /* look for existing session */
2428  &address->peer))
2429  {
2430  struct GNUNET_ATS_SessionItCtx si_ctx;
2431 
2432  si_ctx.address = address;
2433  si_ctx.result = NULL;
2435  &address->peer,
2437  &si_ctx);
2438  if (NULL != si_ctx.result)
2439  {
2440  session = si_ctx.result;
2442  "Found existing session for `%s' address `%s'\n",
2443  GNUNET_i2s (&address->peer),
2445  address->address,
2446  address->address_length));
2447  return session;
2448  }
2449  /* This is a bit of a hack, limiting TCP to never allow more than
2450  one TCP connection to any given peer at the same time.
2451  Without this, peers sometimes disagree about which of the TCP
2452  connections they should use, causing one side to believe that
2453  they transmit successfully, while the other receives nothing. */return NULL; /* Refuse to have more than one TCP connection per
2454  peer pair at the same time. */
2455  }
2456 
2457  if (addrlen == sizeof(struct IPv6TcpAddress))
2458  {
2459  GNUNET_assert (NULL != address->address); /* make static analysis happy */
2460  t6 = address->address;
2461  options = t6->options;
2462  af = AF_INET6;
2463  memset (&a6, 0, sizeof(a6));
2464 #if HAVE_SOCKADDR_IN_SIN_LEN
2465  a6.sin6_len = sizeof(a6);
2466 #endif
2467  a6.sin6_family = AF_INET6;
2468  a6.sin6_port = t6->t6_port;
2469  if (t6->t6_port == 0)
2470  is_natd = GNUNET_YES;
2471  GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
2472  sb = &a6;
2473  sbs = sizeof(a6);
2474  }
2475  else if (addrlen == sizeof(struct IPv4TcpAddress))
2476  {
2477  GNUNET_assert (NULL != address->address); /* make static analysis happy */
2478  t4 = address->address;
2479  options = t4->options;
2480  af = AF_INET;
2481  memset (&a4, 0, sizeof(a4));
2482 #if HAVE_SOCKADDR_IN_SIN_LEN
2483  a4.sin_len = sizeof(a4);
2484 #endif
2485  a4.sin_family = AF_INET;
2486  a4.sin_port = t4->t4_port;
2487  if (t4->t4_port == 0)
2488  is_natd = GNUNET_YES;
2489  a4.sin_addr.s_addr = t4->ipv4_addr;
2490  sb = &a4;
2491  sbs = sizeof(a4);
2492  }
2493  else
2494  {
2496  plugin->env->stats,
2497  gettext_noop ("# requests to create session with invalid address"),
2498  1,
2499  GNUNET_NO);
2500  return NULL;
2501  }
2502 
2503  net_type = plugin->env->get_address_type (plugin->env->cls, sb, sbs);
2504  GNUNET_break (net_type != GNUNET_NT_UNSPECIFIED);
2505 
2506  if ((is_natd == GNUNET_YES) && (addrlen == sizeof(struct IPv6TcpAddress)))
2507  {
2508  /* NAT client only works with IPv4 addresses */
2509  return NULL;
2510  }
2511 
2512  if (plugin->cur_connections >= plugin->max_connections)
2513  {
2514  /* saturated */
2515  return NULL;
2516  }
2517 
2518  if ((is_natd == GNUNET_YES) &&
2519  (GNUNET_YES ==
2521  &address->peer)))
2522  {
2523  /* Only do one NAT punch attempt per peer identity */
2524  return NULL;
2525  }
2526 
2527  if ((is_natd == GNUNET_YES) && (NULL != plugin->nat) &&
2528  (GNUNET_NO ==
2530  &address->peer)))
2531  {
2532  struct sockaddr_in local_sa;
2533 
2535  "Found valid IPv4 NAT address (creating session)!\n");
2536  session = create_session (plugin, address, net_type, NULL, GNUNET_YES);
2537  session->nat_connection_timeout =
2541  plugin->nat_wait_conns,
2542  &session->target,
2543  session,
2545 
2547  "Created NAT WAIT connection to `%s' at `%s'\n",
2548  GNUNET_i2s (&session->target),
2549  GNUNET_a2s (sb, sbs));
2550  memset (&local_sa, 0, sizeof(local_sa));
2551  local_sa.sin_family = AF_INET;
2552  local_sa.sin_port = htons (plugin->open_port);
2553  /* We leave sin_address at 0, let the kernel figure it out,
2554  even if our bind() is more specific. (May want to reconsider
2555  later.) */
2556  if (GNUNET_OK == GNUNET_NAT_request_reversal (plugin->nat, &local_sa, &a4))
2557  return session;
2559  "Running NAT client for `%s' at `%s' failed\n",
2560  GNUNET_i2s (&session->target),
2561  GNUNET_a2s (sb, sbs));
2563  return NULL;
2564  }
2565 
2566  /* create new outbound session */
2567  if (0 != (options & TCP_OPTIONS_TCP_STEALTH))
2568  {
2569 #ifdef TCP_STEALTH
2570  s = GNUNET_NETWORK_socket_create (af, SOCK_STREAM, 0);
2571  if (NULL == s)
2572  {
2574  "socket");
2575  sa = NULL;
2576  }
2577  else
2578  {
2579  if ((GNUNET_OK !=
2581  IPPROTO_TCP,
2582  TCP_STEALTH,
2583  &session->target,
2584  sizeof(
2585  struct GNUNET_PeerIdentity))) ||
2586  (GNUNET_OK !=
2588  IPPROTO_TCP,
2589  TCP_STEALTH_INTEGRITY,
2590  &plugin->my_welcome,
2591  sizeof(struct WelcomeMessage))))
2592  {
2593  /* TCP STEALTH not supported by kernel */
2595  sa = NULL;
2596  }
2597  else
2598  {
2599  sa = GNUNET_CONNECTION_connect_socket (s, sb, sbs);
2600  }
2601  }
2602 #else
2603  sa = NULL;
2604 #endif
2605  }
2606  else
2607  {
2608  sa = GNUNET_CONNECTION_create_from_sockaddr (af, sb, sbs);
2609  }
2610  if (NULL == sa)
2611  {
2613  "Failed to create connection to `%s' at `%s'\n",
2614  GNUNET_i2s (&address->peer),
2615  GNUNET_a2s (sb, sbs));
2616  return NULL;
2617  }
2619  "Asked to transmit to `%s', creating fresh session using address `%s'.\n",
2620  GNUNET_i2s (&address->peer),
2621  GNUNET_a2s (sb, sbs));
2622 
2623  session = create_session (plugin,
2624  address,
2625  net_type,
2626  GNUNET_SERVER_connect_socket (plugin->server, sa),
2627  GNUNET_NO);
2629  plugin->sessionmap,
2630  &session->target,
2631  session,
2633  /* Send TCP Welcome */
2634  process_pending_messages (session);
2635 
2636  return session;
2637 }
2638 
2639 
2650 static int
2652  const struct GNUNET_PeerIdentity *key,
2653  void *value)
2654 {
2655  struct Plugin *plugin = cls;
2656  struct GNUNET_ATS_Session *session = value;
2657 
2658  GNUNET_STATISTICS_update (session->plugin->env->stats,
2659  gettext_noop (
2660  "# transport-service disconnect requests for TCP"),
2661  1,
2662  GNUNET_NO);
2664  return GNUNET_YES;
2665 }
2666 
2667 
2684 static void
2686 {
2687  struct Plugin *plugin = cls;
2688 
2690  "Disconnecting peer `%s'\n",
2691  GNUNET_i2s (target));
2693  target,
2695  plugin);
2697  target,
2699  plugin);
2700 }
2701 
2702 
2713 static void
2714 append_port (void *cls, const char *hostname)
2715 {
2716  struct PrettyPrinterContext *ppc = cls;
2717  struct Plugin *plugin = ppc->plugin;
2718  char *ret;
2719 
2721  "append_port called with hostname `%s'\n",
2722  hostname);
2723  if (NULL == hostname)
2724  {
2725  /* Final call, done */
2726  ppc->resolver_handle = NULL;
2727  GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
2728  plugin->ppc_dll_tail,
2729  ppc);
2730  ppc->asc (ppc->asc_cls, NULL, GNUNET_OK);
2731  GNUNET_free (ppc);
2732  return;
2733  }
2734  if (GNUNET_YES == ppc->ipv6)
2735  GNUNET_asprintf (&ret,
2736  "%s.%u.[%s]:%d",
2737  PLUGIN_NAME,
2738  ppc->options,
2739  hostname,
2740  ppc->port);
2741  else
2742  GNUNET_asprintf (&ret,
2743  "%s.%u.%s:%d",
2744  PLUGIN_NAME,
2745  ppc->options,
2746  hostname,
2747  ppc->port);
2748  ppc->asc (ppc->asc_cls, ret, GNUNET_OK);
2749  GNUNET_free (ret);
2750 }
2751 
2752 
2766 static void
2768  const char *type,
2769  const void *addr,
2770  size_t addrlen,
2771  int numeric,
2774  void *asc_cls)
2775 {
2776  struct Plugin *plugin = cls;
2777  struct PrettyPrinterContext *ppc;
2778  const void *sb;
2779  size_t sbs;
2780  struct sockaddr_in a4;
2781  struct sockaddr_in6 a6;
2782  const struct IPv4TcpAddress *t4;
2783  const struct IPv6TcpAddress *t6;
2784  uint16_t port;
2785  uint32_t options;
2786 
2787  if (sizeof(struct IPv6TcpAddress) == addrlen)
2788  {
2789  t6 = addr;
2790  memset (&a6, 0, sizeof(a6));
2791  a6.sin6_family = AF_INET6;
2792  a6.sin6_port = t6->t6_port;
2793  GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
2794  port = ntohs (t6->t6_port);
2795  options = ntohl (t6->options);
2796  sb = &a6;
2797  sbs = sizeof(a6);
2798  }
2799  else if (sizeof(struct IPv4TcpAddress) == addrlen)
2800  {
2801  t4 = addr;
2802  memset (&a4, 0, sizeof(a4));
2803  a4.sin_family = AF_INET;
2804  a4.sin_port = t4->t4_port;
2805  a4.sin_addr.s_addr = t4->ipv4_addr;
2806  port = ntohs (t4->t4_port);
2807  options = ntohl (t4->options);
2808  sb = &a4;
2809  sbs = sizeof(a4);
2810  }
2811  else
2812  {
2813  /* invalid address */
2815  _ ("Unexpected address length: %u bytes\n"),
2816  (unsigned int) addrlen);
2817  asc (asc_cls, NULL, GNUNET_SYSERR);
2818  asc (asc_cls, NULL, GNUNET_OK);
2819  return;
2820  }
2821  ppc = GNUNET_new (struct PrettyPrinterContext);
2822  ppc->plugin = plugin;
2823  if (addrlen == sizeof(struct IPv6TcpAddress))
2824  ppc->ipv6 = GNUNET_YES;
2825  else
2826  ppc->ipv6 = GNUNET_NO;
2827  ppc->asc = asc;
2828  ppc->asc_cls = asc_cls;
2829  ppc->port = port;
2830  ppc->options = options;
2831  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting DNS reverse lookup\n");
2833  sbs,
2834  ! numeric,
2835  timeout,
2836  &append_port,
2837  ppc);
2838  if (NULL == ppc->resolver_handle)
2839  {
2840  GNUNET_break (0);
2841  GNUNET_free (ppc);
2842  return;
2843  }
2844  GNUNET_CONTAINER_DLL_insert (plugin->ppc_dll_head, plugin->ppc_dll_tail, ppc);
2845 }
2846 
2847 
2863 static int
2864 tcp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
2865 {
2866  struct Plugin *plugin = cls;
2867  const struct IPv4TcpAddress *v4;
2868  const struct IPv6TcpAddress *v6;
2869 
2870  if ((addrlen != sizeof(struct IPv4TcpAddress)) &&
2871  (addrlen != sizeof(struct IPv6TcpAddress)))
2872  {
2873  GNUNET_break_op (0);
2874  return GNUNET_SYSERR;
2875  }
2876 
2877  if (addrlen == sizeof(struct IPv4TcpAddress))
2878  {
2879  struct sockaddr_in s4;
2880 
2881  v4 = (const struct IPv4TcpAddress *) addr;
2882  if (0 != memcmp (&v4->options, &plugin->myoptions, sizeof(uint32_t)))
2883  {
2884  GNUNET_break (0);
2885  return GNUNET_SYSERR;
2886  }
2887  memset (&s4, 0, sizeof(s4));
2888  s4.sin_family = AF_INET;
2889 #if HAVE_SOCKADDR_IN_SIN_LEN
2890  s4.sin_len = sizeof(s4);
2891 #endif
2892  s4.sin_port = v4->t4_port;
2893  s4.sin_addr.s_addr = v4->ipv4_addr;
2894 
2895  if (GNUNET_OK !=
2896  GNUNET_NAT_test_address (plugin->nat, &s4, sizeof(struct sockaddr_in)))
2897  return GNUNET_SYSERR;
2898  }
2899  else
2900  {
2901  struct sockaddr_in6 s6;
2902 
2903  v6 = (const struct IPv6TcpAddress *) addr;
2904  if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
2905  {
2906  GNUNET_break_op (0);
2907  return GNUNET_SYSERR;
2908  }
2909  if (0 != memcmp (&v6->options, &plugin->myoptions, sizeof(uint32_t)))
2910  {
2911  GNUNET_break (0);
2912  return GNUNET_SYSERR;
2913  }
2914  memset (&s6, 0, sizeof(s6));
2915  s6.sin6_family = AF_INET6;
2916 #if HAVE_SOCKADDR_IN_SIN_LEN
2917  s6.sin6_len = sizeof(s6);
2918 #endif
2919  s6.sin6_port = v6->t6_port;
2920  s6.sin6_addr = v6->ipv6_addr;
2921 
2923  &s6,
2924  sizeof(struct sockaddr_in6)))
2925  return GNUNET_SYSERR;
2926  }
2927  return GNUNET_OK;
2928 }
2929 
2930 
2940 static void
2942  struct GNUNET_SERVER_Client *client,
2943  const struct GNUNET_MessageHeader *message)
2944 {
2945  struct Plugin *plugin = cls;
2946  struct GNUNET_ATS_Session *session;
2947  const struct TCP_NAT_ProbeMessage *tcp_nat_probe;
2948  size_t alen;
2949  void *vaddr;
2950  struct IPv4TcpAddress *t4;
2951  struct IPv6TcpAddress *t6;
2952  const struct sockaddr_in *s4;
2953  const struct sockaddr_in6 *s6;
2954 
2955  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received NAT probe\n");
2956  /* We have received a TCP NAT probe, meaning we (hopefully) initiated
2957  * a connection to this peer by running gnunet-nat-client. This peer
2958  * received the punch message and now wants us to use the new connection
2959  * as the default for that peer. Do so and then send a WELCOME message
2960  * so we can really be connected!
2961  */if (ntohs (message->size) != sizeof(struct TCP_NAT_ProbeMessage))
2962  {
2963  GNUNET_break_op (0);
2965  return;
2966  }
2967 
2968  tcp_nat_probe = (const struct TCP_NAT_ProbeMessage *) message;
2969  if (0 == memcmp (&tcp_nat_probe->clientIdentity,
2970  plugin->env->my_identity,
2971  sizeof(struct GNUNET_PeerIdentity)))
2972  {
2973  /* refuse connections from ourselves */
2975  return;
2976  }
2977 
2978  session = GNUNET_CONTAINER_multipeermap_get (plugin->nat_wait_conns,
2979  &tcp_nat_probe->clientIdentity);
2980  if (NULL == session)
2981  {
2982  LOG (GNUNET_ERROR_TYPE_DEBUG, "Did NOT find session for NAT probe!\n");
2984  return;
2985  }
2986  LOG (GNUNET_ERROR_TYPE_DEBUG, "Found session for NAT probe!\n");
2987 
2988  if (NULL != session->nat_connection_timeout)
2989  {
2991  session->nat_connection_timeout = NULL;
2992  }
2993 
2994  if (GNUNET_OK != GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
2995  {
2996  GNUNET_break (0);
2999  return;
3000  }
3001  GNUNET_assert (
3002  GNUNET_YES ==
3004  &tcp_nat_probe->clientIdentity,
3005  session));
3006  GNUNET_SERVER_client_set_user_context (client, session);
3008  plugin->sessionmap,
3009  &session->target,
3010  session,
3014  "Found address `%s' for incoming connection\n",
3015  GNUNET_a2s (vaddr, alen));
3016  switch (((const struct sockaddr *) vaddr)->sa_family)
3017  {
3018  case AF_INET:
3019  s4 = vaddr;
3020  t4 = GNUNET_new (struct IPv4TcpAddress);
3021  t4->options = htonl (TCP_OPTIONS_NONE);
3022  t4->t4_port = s4->sin_port;
3023  t4->ipv4_addr = s4->sin_addr.s_addr;
3024  session->address =
3026  PLUGIN_NAME,
3027  &t4,
3028  sizeof(struct IPv4TcpAddress),
3030  break;
3031 
3032  case AF_INET6:
3033  s6 = vaddr;
3034  t6 = GNUNET_new (struct IPv6TcpAddress);
3035  t6->options = htonl (TCP_OPTIONS_NONE);
3036  t6->t6_port = s6->sin6_port;
3037  GNUNET_memcpy (&t6->ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
3038  session->address =
3040  PLUGIN_NAME,
3041  &t6,
3042  sizeof(struct IPv6TcpAddress),
3044  break;
3045 
3046  default:
3047  GNUNET_break_op (0);
3048  LOG (GNUNET_ERROR_TYPE_DEBUG, "Bad address for incoming connection!\n");
3049  GNUNET_free (vaddr);
3052  return;
3053  }
3054  GNUNET_free (vaddr);
3055  GNUNET_break (NULL == session->client);
3056  session->client = client;
3057  GNUNET_STATISTICS_update (plugin->env->stats,
3058  gettext_noop ("# TCP sessions active"),
3059  1,
3060  GNUNET_NO);
3061  process_pending_messages (session);
3063 }
3064 
3065 
3074 static void
3076  struct GNUNET_SERVER_Client *client,
3077  const struct GNUNET_MessageHeader *message)
3078 {
3079  struct Plugin *plugin = cls;
3080  const struct WelcomeMessage *wm = (const struct WelcomeMessage *) message;
3081  struct GNUNET_HELLO_Address *address;
3082  struct GNUNET_ATS_Session *session;
3083  size_t alen;
3084  void *vaddr;
3085  struct IPv4TcpAddress t4;
3086  struct IPv6TcpAddress t6;
3087  const struct sockaddr_in *s4;
3088  const struct sockaddr_in6 *s6;
3089 
3090  if (0 == memcmp (&wm->clientIdentity,
3091  plugin->env->my_identity,
3092  sizeof(struct GNUNET_PeerIdentity)))
3093  {
3094  /* refuse connections from ourselves */
3095  if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
3096  {
3098  "Received WELCOME message from my own identity `%s' on address `%s'\n",
3099  GNUNET_i2s (&wm->clientIdentity),
3100  GNUNET_a2s (vaddr, alen));
3101  GNUNET_free (vaddr);
3102  }
3104  return;
3105  }
3106 
3107  if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
3108  {
3110  "Received WELCOME message from `%s' on address `%s'\n",
3111  GNUNET_i2s (&wm->clientIdentity),
3112  GNUNET_a2s (vaddr, alen));
3113  GNUNET_free (vaddr);
3114  }
3115  GNUNET_STATISTICS_update (plugin->env->stats,
3116  gettext_noop ("# TCP WELCOME messages received"),
3117  1,
3118  GNUNET_NO);
3119  session = lookup_session_by_client (plugin, client);
3120  if (NULL != session)
3121  {
3122  if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
3123  {
3125  "Found existing session %p for peer `%s'\n",
3126  session,
3127  GNUNET_a2s (vaddr, alen));
3128  GNUNET_free (vaddr);
3129  }
3130  }
3131  else
3132  {
3133  if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
3134  {
3135  if (alen == sizeof(struct sockaddr_in))
3136  {
3137  s4 = vaddr;
3138  memset (&t4, '\0', sizeof(t4));
3139  t4.options = htonl (TCP_OPTIONS_NONE);
3140  t4.t4_port = s4->sin_port;
3141  t4.ipv4_addr = s4->sin_addr.s_addr;
3142  address =
3144  PLUGIN_NAME,
3145  &t4,
3146  sizeof(t4),
3148  }
3149  else if (alen == sizeof(struct sockaddr_in6))
3150  {
3151  s6 = vaddr;
3152  memset (&t6, '\0', sizeof(t6));
3153  t6.options = htonl (TCP_OPTIONS_NONE);
3154  t6.t6_port = s6->sin6_port;
3155  GNUNET_memcpy (&t6.ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
3156  address =
3158  PLUGIN_NAME,
3159  &t6,
3160  sizeof(t6),
3162  }
3163  else
3164  {
3165  GNUNET_break (0);
3166  GNUNET_free (vaddr);
3168  return;
3169  }
3170  session = create_session (plugin,
3171  address,
3172  plugin->env->get_address_type (plugin->env->cls,
3173  vaddr,
3174  alen),
3175  client,
3176  GNUNET_NO);
3180  "Creating new%s session %p for peer `%s' client %p\n",
3183  ? " inbound"
3184  : "",
3185  session,
3187  session->address->address,
3188  session->address->address_length),
3189  client);
3190  GNUNET_free (vaddr);
3192  plugin->sessionmap,
3193  &session->target,
3194  session,
3196  /* Notify transport and ATS about new session */
3197  plugin->env->session_start (plugin->env->cls,
3198  session->address,
3199  session,
3200  session->scope);
3201  }
3202  else
3203  {
3205  "Did not obtain TCP socket address for incoming connection\n");
3206  GNUNET_break (0);
3208  return;
3209  }
3210  }
3211 
3212  if (GNUNET_YES != session->expecting_welcome)
3213  {
3214  GNUNET_break_op (0);
3216  return;
3217  }
3219  session->expecting_welcome = GNUNET_NO;
3220 
3221  process_pending_messages (session);
3225 }
3226 
3227 
3236 static void
3237 handle_tcp_data (void *cls,
3238  struct GNUNET_SERVER_Client *client,
3239  const struct GNUNET_MessageHeader *message)
3240 {
3241  struct Plugin *plugin = cls;
3242  struct GNUNET_ATS_Session *session;
3243  struct GNUNET_TIME_Relative delay;
3244  uint16_t type;
3245 
3246  type = ntohs (message->type);
3249  {
3250  /* We don't want to propagate WELCOME and NAT Probe messages up! */
3252  return;
3253  }
3254  session = lookup_session_by_client (plugin, client);
3255  if (NULL == session)
3256  {
3257  /* No inbound session found */
3258  void *vaddr = NULL;
3259  size_t alen;
3260 
3262  GNUNET_SERVER_client_get_address (client, &vaddr, &alen));
3264  "Received unexpected %u bytes of type %u from `%s'\n",
3265  (unsigned int) ntohs (message->size),
3266  (unsigned int) ntohs (message->type),
3267  GNUNET_a2s (vaddr, alen));
3268  GNUNET_break_op (0);
3270  GNUNET_free (vaddr);
3271  return;
3272  }
3273  if (GNUNET_YES == session->expecting_welcome)
3274  {
3275  /* Session is expecting WELCOME message */
3276  void *vaddr = NULL;
3277  size_t alen;
3278 
3279  GNUNET_SERVER_client_get_address (client, &vaddr, &alen);
3281  "Received unexpected %u bytes of type %u from `%s'\n",
3282  (unsigned int) ntohs (message->size),
3283  (unsigned int) ntohs (message->type),
3284  GNUNET_a2s (vaddr, alen));
3285  GNUNET_break_op (0);
3287  GNUNET_free (vaddr);
3288  return;
3289  }
3290 
3292  {
3293  void *vaddr = NULL;
3294  size_t alen;
3295 
3296  GNUNET_SERVER_client_get_address (client, &vaddr, &alen);
3298  "Passing %u bytes of type %u from `%s' at %s to transport service.\n",
3299  (unsigned int) ntohs (message->size),
3300  (unsigned int) ntohs (message->type),
3301  GNUNET_i2s (&session->target),
3302  GNUNET_a2s (vaddr, alen));
3303  GNUNET_free (vaddr);
3304  }
3305 
3306  GNUNET_STATISTICS_update (plugin->env->stats,
3307  gettext_noop ("# bytes received via TCP"),
3308  ntohs (message->size),
3309  GNUNET_NO);
3310 
3311  GNUNET_assert (
3313  &session->target,
3314  session));
3315  delay =
3316  plugin->env->receive (plugin->env->cls, session->address, session, message);
3317  reschedule_session_timeout (session);
3318  if (0 == delay.rel_value_us)
3319  {
3321  }
3322  else
3323  {
3325  "Throttling receiving from `%s' for %s\n",
3326  GNUNET_i2s (&session->target),
3329  GNUNET_assert (NULL == session->receive_delay_task);
3330  session->receive_delay_task =
3332  }
3333 }
3334 
3335 
3344 static void
3345 connect_notify (void *cls, struct GNUNET_SERVER_Client *client)
3346 {
3347  struct Plugin *plugin = cls;
3348 
3349  if (NULL == client)
3350  return;
3351  plugin->cur_connections++;
3352  GNUNET_STATISTICS_set (plugin->env->stats,
3353  gettext_noop ("# TCP server connections active"),
3354  plugin->cur_connections,
3355  GNUNET_NO);
3356  GNUNET_STATISTICS_update (plugin->env->stats,
3357  gettext_noop ("# TCP server connect events"),
3358  1,
3359  GNUNET_NO);
3360  if (plugin->cur_connections != plugin->max_connections)
3361  return;
3363  _ ("TCP connection limit reached, suspending server\n"));
3364  GNUNET_STATISTICS_update (plugin->env->stats,
3365  gettext_noop ("# TCP service suspended"),
3366  1,
3367  GNUNET_NO);
3369  plugin->server); /* Maximum number of connections rechead */
3370 }
3371 
3372 
3381 static void
3382 disconnect_notify (void *cls, struct GNUNET_SERVER_Client *client)
3383 {
3384  struct Plugin *plugin = cls;
3385  struct GNUNET_ATS_Session *session;
3386 
3387  if (NULL == client)
3388  return;
3389  GNUNET_assert (plugin->cur_connections >= 1);
3390  plugin->cur_connections--;
3391  session = lookup_session_by_client (plugin, client);
3392  if (NULL == session)
3393  return; /* unknown, nothing to do */
3395  "Destroying session of `%s' with %s due to network-level disconnect.\n",
3396  GNUNET_i2s (&session->target),
3398  session->address->address,
3399  session->address->address_length));
3400 
3401  if (plugin->cur_connections == plugin->max_connections)
3402  {
3403  GNUNET_STATISTICS_update (session->plugin->env->stats,
3404  gettext_noop ("# TCP service resumed"),
3405  1,
3406  GNUNET_NO);
3407  GNUNET_SERVER_resume (plugin->server); /* Resume server */
3408  }
3409  GNUNET_STATISTICS_set (plugin->env->stats,
3410  gettext_noop ("# TCP server connections active"),
3411  plugin->cur_connections,
3412  GNUNET_NO);
3413  GNUNET_STATISTICS_update (session->plugin->env->stats,
3414  gettext_noop (
3415  "# network-level TCP disconnect events"),
3416  1,
3417  GNUNET_NO);
3419 }
3420 
3421 
3430 static size_t
3431 notify_send_probe (void *cls, size_t size, void *buf)
3432 {
3433  struct TCPProbeContext *tcp_probe_ctx = cls;
3434  struct Plugin *plugin = tcp_probe_ctx->plugin;
3435  size_t ret;
3436 
3437  tcp_probe_ctx->transmit_handle = NULL;
3438  GNUNET_CONTAINER_DLL_remove (plugin->probe_head,
3439  plugin->probe_tail,
3440  tcp_probe_ctx);
3441  if (NULL == buf)
3442  {
3443  GNUNET_CONNECTION_destroy (tcp_probe_ctx->sock);
3444  GNUNET_free (tcp_probe_ctx);
3445  return 0;
3446  }
3447  GNUNET_assert (size >= sizeof(tcp_probe_ctx->message));
3448  GNUNET_memcpy (buf, &tcp_probe_ctx->message, sizeof(tcp_probe_ctx->message));
3449  GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server,
3450  tcp_probe_ctx->sock);
3451  ret = sizeof(tcp_probe_ctx->message);
3452  GNUNET_free (tcp_probe_ctx);
3453  return ret;
3454 }
3455 
3456 
3466 static void
3468  const struct sockaddr *addr,
3469  socklen_t addrlen)
3470 {
3471  struct Plugin *plugin = cls;
3473  struct TCPProbeContext *tcp_probe_ctx;
3474 
3479  sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen);
3480  if (NULL == sock)
3481  {
3482  /* failed for some odd reason (out of sockets?); ignore attempt */
3483  return;
3484  }
3485 
3486  tcp_probe_ctx = GNUNET_new (struct TCPProbeContext);
3487  tcp_probe_ctx->message.header.size =
3488  htons (sizeof(struct TCP_NAT_ProbeMessage));
3489  tcp_probe_ctx->message.header.type =
3491  tcp_probe_ctx->message.clientIdentity = *plugin->env->my_identity;
3492  tcp_probe_ctx->plugin = plugin;
3493  tcp_probe_ctx->sock = sock;
3494  GNUNET_CONTAINER_DLL_insert (plugin->probe_head,
3495  plugin->probe_tail,
3496  tcp_probe_ctx);
3497  tcp_probe_ctx->transmit_handle =
3499  ntohs (tcp_probe_ctx->message
3500  .header.size),
3503  tcp_probe_ctx);
3504 }
3505 
3506 
3514 static enum GNUNET_NetworkType
3515 tcp_plugin_get_network (void *cls, struct GNUNET_ATS_Session *session)
3516 {
3517  return session->scope;
3518 }
3519 
3520 
3528 static enum GNUNET_NetworkType
3530  const struct GNUNET_HELLO_Address *address)
3531 {
3532  struct Plugin *plugin = cls;
3533  size_t addrlen;
3534  struct sockaddr_in a4;
3535  struct sockaddr_in6 a6;
3536  const struct IPv4TcpAddress *t4;
3537  const struct IPv6TcpAddress *t6;
3538  const void *sb;
3539  size_t sbs;
3540 
3541  addrlen = address->address_length;
3542  if (addrlen == sizeof(struct IPv6TcpAddress))
3543  {
3544  GNUNET_assert (NULL != address->address); /* make static analysis happy */
3545  t6 = address->address;
3546  memset (&a6, 0, sizeof(a6));
3547 #if HAVE_SOCKADDR_IN_SIN_LEN
3548  a6.sin6_len = sizeof(a6);
3549 #endif
3550  a6.sin6_family = AF_INET6;
3551  a6.sin6_port = t6->t6_port;
3552  GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
3553  sb = &a6;
3554  sbs = sizeof(a6);
3555  }
3556  else if (addrlen == sizeof(struct IPv4TcpAddress))
3557  {
3558  GNUNET_assert (NULL != address->address); /* make static analysis happy */
3559  t4 = address->address;
3560  memset (&a4, 0, sizeof(a4));
3561 #if HAVE_SOCKADDR_IN_SIN_LEN
3562  a4.sin_len = sizeof(a4);
3563 #endif
3564  a4.sin_family = AF_INET;
3565  a4.sin_port = t4->t4_port;
3566  a4.sin_addr.s_addr = t4->ipv4_addr;
3567  sb = &a4;
3568  sbs = sizeof(a4);
3569  }
3570  else
3571  {
3572  GNUNET_break (0);
3573  return GNUNET_NT_UNSPECIFIED;
3574  }
3575  return plugin->env->get_address_type (plugin->env->cls, sb, sbs);
3576 }
3577 
3578 
3588 static int
3590  const struct GNUNET_PeerIdentity *peer,
3591  void *value)
3592 {
3593  struct Plugin *plugin = cls;
3594  struct GNUNET_ATS_Session *session = value;
3595 
3597  /* FIXME: cannot tell if this is up or not from current
3598  session state... */
3600  return GNUNET_OK;
3601 }
3602 
3603 
3616 static void
3619  void *sic_cls)
3620 {
3621  struct Plugin *plugin = cls;
3622 
3623  plugin->sic = sic;
3624  plugin->sic_cls = sic_cls;
3625  if (NULL != sic)
3626  {
3629  plugin);
3630  /* signal end of first iteration */
3631  sic (sic_cls, NULL, NULL);
3632  }
3633 }
3634 
3635 
3642 void *
3644 {
3645  static const struct GNUNET_SERVER_MessageHandler my_handlers[] =
3646  { { &handle_tcp_welcome,
3647  NULL,
3649  sizeof(struct WelcomeMessage) },
3651  NULL,
3653  sizeof(struct TCP_NAT_ProbeMessage) },
3655  { NULL, NULL, 0, 0 } };
3658  struct Plugin *plugin;
3660  unsigned long long aport;
3661  unsigned long long bport;
3662  unsigned long long max_connections;
3663  unsigned int i;
3664  struct GNUNET_TIME_Relative idle_timeout;
3665 
3666 #ifdef TCP_STEALTH
3667  struct GNUNET_NETWORK_Handle *const *lsocks;
3668 #endif
3669  int ret;
3670  int ret_s;
3671  struct sockaddr **addrs;
3672  socklen_t *addrlens;
3673 
3674  if (NULL == env->receive)
3675  {
3676  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
3677  initialize the plugin or the API */
3679  api->cls = NULL;
3683  return api;
3684  }
3685 
3686  GNUNET_assert (NULL != env->cfg);
3688  "transport-tcp",
3689  "MAX_CONNECTIONS",
3690  &max_connections))
3691  max_connections = 128;
3692 
3693  aport = 0;
3695  "transport-tcp",
3696  "PORT",
3697  &bport)) ||
3698  (bport > 65535) ||
3700  "transport-tcp",
3701  "ADVERTISED-PORT",
3702  &aport)) &&
3703  (aport > 65535)))
3704  {
3706  _ ("Require valid port number for service `%s' in configuration!\n"),
3707  "transport-tcp");
3708  return NULL;
3709  }
3710  if (0 == aport)
3711  aport = bport;
3712  if (0 == bport)
3713  aport = 0;
3714  if (0 != bport)
3715  {
3716  service = LEGACY_SERVICE_start ("transport-tcp",
3717  env->cfg,
3719  if (NULL == service)
3720  {
3721  LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Failed to start service.\n"));
3722  return NULL;
3723  }
3724  }
3725  else
3726  service = NULL;
3727 
3728  api = NULL;
3729  plugin = GNUNET_new (struct Plugin);
3730  plugin->sessionmap =
3732  plugin->max_connections = max_connections;
3733  plugin->open_port = bport;
3734  plugin->adv_port = aport;
3735  plugin->env = env;
3736  plugin->my_welcome.header.size = htons (sizeof(struct WelcomeMessage));
3737  plugin->my_welcome.header.type =
3739  plugin->my_welcome.clientIdentity = *plugin->env->my_identity;
3740 
3741  if ((NULL != service) &&
3743  "transport-tcp",
3744  "TCP_STEALTH")))
3745  {
3746 #ifdef TCP_STEALTH
3747  plugin->myoptions |= TCP_OPTIONS_TCP_STEALTH;
3749  if (NULL != lsocks)
3750  {
3751  uint32_t len = sizeof(struct WelcomeMessage);
3752 
3753  for (i = 0; NULL != lsocks[i]; i++)
3754  {
3755  if (
3756  (GNUNET_OK !=
3758  IPPROTO_TCP,
3759  TCP_STEALTH,
3760  env->my_identity,
3761  sizeof(
3762  struct GNUNET_PeerIdentity))) ||
3763  (GNUNET_OK !=
3765  IPPROTO_TCP,
3766  TCP_STEALTH_INTEGRITY_LEN,
3767  &len,
3768  sizeof(len))))
3769  {
3770  /* TCP STEALTH not supported by kernel */
3771  GNUNET_assert (0 == i);
3773  _ ("TCP_STEALTH not supported on this platform.\n"));
3774  goto die;
3775  }
3776  }
3777  }
3778 #else
3780  _ ("TCP_STEALTH not supported on this platform.\n"));
3781  goto die;
3782 #endif
3783  }
3784 
3785  if ((NULL != service) &&
3786  (GNUNET_SYSERR !=
3787  (ret_s =
3788  get_server_addresses ("transport-tcp", env->cfg, &addrs, &addrlens))))
3789  {
3790  for (ret = ret_s - 1; ret >= 0; ret--)
3792  "Binding to address `%s'\n",
3793  GNUNET_a2s (addrs[ret], addrlens[ret]));
3794  plugin->nat = GNUNET_NAT_register (env->cfg,
3795  "transport-tcp",
3796  IPPROTO_TCP,
3797  (unsigned int) ret_s,
3798  (const struct sockaddr **) addrs,
3799  addrlens,
3802  plugin);
3803  for (ret = ret_s - 1; ret >= 0; ret--)
3804  GNUNET_free (addrs[ret]);
3805  GNUNET_free (addrs);
3806  GNUNET_free (addrlens);
3807  }
3808  else
3809  {
3810  plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
3811  "transport-tcp",
3812  IPPROTO_TCP,
3813  0,
3814  NULL,
3815  NULL,
3816  NULL,
3818  plugin);
3819  }
3821  api->cls = plugin;
3822  api->send = &tcp_plugin_send;
3836  plugin->service = service;
3837  if (NULL != service)
3838  {
3840  }
3841  else
3842  {
3844  "transport-tcp",
3845  "TIMEOUT",
3846  &idle_timeout))
3847  {
3849  "transport-tcp",
3850  "TIMEOUT");
3851  goto die;
3852  }
3853  plugin->server = GNUNET_SERVER_create_with_sockets (NULL,
3854  plugin,
3855  NULL,
3856  idle_timeout,
3857  GNUNET_YES);
3858  }
3859  plugin->handlers = GNUNET_malloc (sizeof(my_handlers));
3860  GNUNET_memcpy (plugin->handlers, my_handlers, sizeof(my_handlers));
3861  for (i = 0;
3862  i < sizeof(my_handlers) / sizeof(struct GNUNET_SERVER_MessageHandler);
3863  i++)
3864  plugin->handlers[i].callback_cls = plugin;
3865 
3866  GNUNET_SERVER_add_handlers (plugin->server, plugin->handlers);
3869  plugin->nat_wait_conns =
3871  if (0 != bport)
3873  _ ("TCP transport listening on port %llu\n"),
3874  bport);
3875  else
3877  _ ("TCP transport not listening on any port (client only)\n"));
3878  if ((aport != bport) && (0 != bport))
3880  _ ("TCP transport advertises itself as being on port %llu\n"),
3881  aport);
3882  /* Initially set connections to 0 */
3883  GNUNET_STATISTICS_set (plugin->env->stats,
3884  gettext_noop ("# TCP sessions active"),
3885  0,
3886  GNUNET_NO);
3887  return api;
3888 
3889 die:
3890  if (NULL != plugin->nat)
3893  if (NULL != service)
3895  GNUNET_free (plugin);
3896  GNUNET_free (api);
3897  return NULL;
3898 }
3899 
3900 
3907 void *
3909 {
3910  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
3911  struct Plugin *plugin = api->cls;
3912  struct TCPProbeContext *tcp_probe;
3913  struct PrettyPrinterContext *cur;
3914  struct PrettyPrinterContext *next;
3915 
3916  if (NULL == plugin)
3917  {
3918  GNUNET_free (api);
3919  return NULL;
3920  }
3921  LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down TCP plugin\n");
3922 
3923  /* Removing leftover sessions */
3926  plugin);
3927  /* Removing leftover NAT sessions */
3930  plugin);
3931 
3932  for (cur = plugin->ppc_dll_head; NULL != cur; cur = next)
3933  {
3934  next = cur->next;
3935  GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
3936  plugin->ppc_dll_tail,
3937  cur);
3939  cur->asc (cur->asc_cls, NULL, GNUNET_OK);
3940  GNUNET_free (cur);
3941  }
3942 
3943  if (NULL != plugin->service)
3944  LEGACY_SERVICE_stop (plugin->service);
3945  else
3946  GNUNET_SERVER_destroy (plugin->server);
3947  GNUNET_free (plugin->handlers);
3948  if (NULL != plugin->nat)
3950  while (NULL != (tcp_probe = plugin->probe_head))
3951  {
3952  GNUNET_CONTAINER_DLL_remove (plugin->probe_head,
3953  plugin->probe_tail,
3954  tcp_probe);
3955  GNUNET_CONNECTION_destroy (tcp_probe->sock);
3956  GNUNET_free (tcp_probe);
3957  }
3960  GNUNET_break (0 == plugin->cur_connections);
3961  GNUNET_free (plugin);
3962  GNUNET_free (api);
3963  return NULL;
3964 }
3965 
3966 
3967 /* end of plugin_transport_tcp.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define gettext_noop(String)
Definition: gettext.h:70
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static int res
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
struct TestcasePlugin * plugin
The process handle to the testbed service.
static char * address
GNS address for this phone.
static unsigned long long max_connections
If there are at least this many connections, old ones will be removed.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_SCHEDULER_Task * t4
Task for IPv4 socket.
static struct GNUNET_SCHEDULER_Task * t6
Task for IPv6 socket.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static char * value
Value of the record to add/remove.
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
enum State state
current state of profiling
#define info
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
static void add_unixpath(struct sockaddr **saddrs, socklen_t *saddrlens, const char *unixpath, int abstract)
Add the given UNIX domain path as an address to the list (as the first entry).
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static char * hostname
Our hostname; we give this to all the peers we start.
static char buf[2048]
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static int numeric
Option -n.
static struct GNUNET_TRANSPORT_PluginMonitor * pm
Handle if we are monitoring plugin session activity.
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:50
Helper library for handling HELLOs.
Constants for network protocols.
Functions related to doing DNS lookups.
API to create, modify and access statistics.
Transport service plugin API.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_after(head, tail, other, element)
Insert an element into a DLL after the given other element.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL).
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_contains_value(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Check if the map contains the given value under the given key.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_allocate(const struct GNUNET_PeerIdentity *peer, const char *transport_name, const void *address, size_t address_length, enum GNUNET_HELLO_AddressInfo local_info)
Allocate an address struct.
Definition: address.c:63
#define GNUNET_HELLO_address_free(addr)
Free an address.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:99
int GNUNET_HELLO_address_check_option(const struct GNUNET_HELLO_Address *address, enum GNUNET_HELLO_AddressInfo option)
Check if an address has a local option set.
Definition: address.c:39
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:112
@ GNUNET_HELLO_ADDRESS_INFO_INBOUND
This is an inbound address and cannot be used to initiate an outbound connection to another peer.
@ GNUNET_HELLO_ADDRESS_INFO_NONE
No additional information.
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_log(kind,...)
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
int GNUNET_NAT_request_reversal(struct GNUNET_NAT_Handle *nh, const struct sockaddr_in *local_sa, const struct sockaddr_in *remote_sa)
We learned about a peer (possibly behind NAT) so run the gnunet-nat-client to send dummy ICMP respons...
Definition: nat_api.c:646
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition: nat_api.c:674
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition: nat_api.c:366
int GNUNET_NAT_test_address(struct GNUNET_NAT_Handle *nh, const void *addr, socklen_t addrlen)
Test if the given address is (currently) a plausible IP address for this peer.
Definition: nat_api.c:614
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:509
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:833
char * GNUNET_NETWORK_shorten_unixpath(char *unixpath)
Given a unixpath that is too long (larger than UNIX_PATH_MAX), shorten it to an acceptable length whi...
Definition: network.c:144
int GNUNET_NETWORK_socket_setsockopt(struct GNUNET_NETWORK_Handle *fd, int level, int option_name, const void *option_value, socklen_t option_len)
Set socket option.
Definition: network.c:806
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:39
@ GNUNET_NT_UNSPECIFIED
Category of last resort.
Definition: gnunet_nt_lib.h:43
#define GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE
TCP NAT probe message, send from NAT'd peer to other peer to establish bi-directional communication.
#define GNUNET_MESSAGE_TYPE_ALL
Type used to match 'all' message types.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME
Welcome message between TCP transports.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_get(const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls)
Perform a reverse DNS lookup.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1272
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
enum GNUNET_GenericReturnValue GNUNET_STRINGS_to_address_ip(const char *addr, uint16_t addrlen, struct sockaddr_storage *r_buf)
Tries to convert addr string to an IP (v4 or v6) address.
Definition: strings.c:1134
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:405
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:569
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
void(* GNUNET_TRANSPORT_SessionInfoCallback)(void *cls, struct GNUNET_ATS_Session *session, const struct GNUNET_TRANSPORT_SessionInfo *info)
Function called by the plugin with information about the current sessions managed by the plugin (for ...
void(* GNUNET_TRANSPORT_TransmitContinuation)(void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire)
Function called by the GNUNET_TRANSPORT_TransmitFunction upon "completion".
void(* GNUNET_TRANSPORT_AddressStringCallback)(void *cls, const char *address, int res)
Function called by the pretty printer for the resolved address for each human-readable address obtain...
GNUNET_TRANSPORT_SessionState
Possible states of a session in a plugin.
@ GNUNET_TRANSPORT_SS_INIT
The session was created (first call for each session object).
@ GNUNET_TRANSPORT_SS_HANDSHAKE
Initial session handshake is in progress.
@ GNUNET_TRANSPORT_SS_DONE
Session is being torn down and about to disappear.
@ GNUNET_TRANSPORT_SS_UP
Session is fully UP.
@ GNUNET_TRANSPORT_SS_UPDATE
This is just an update about the session, the state did not change.
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
int(* GNUNET_SERVER_MessageTokenizerCallback)(void *cls, void *client, const struct GNUNET_MessageHeader *message)
Functions with this signature are called whenever a complete message is received by the tokenizer.
void GNUNET_SERVER_client_set_user_context_(struct GNUNET_SERVER_Client *client, void *ptr, size_t size)
Set user context to be associated with the given client.
static void handle_tcp_data(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message)
We've received data for this peer via TCP.
static const char * tcp_plugin_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.
int GNUNET_SERVER_mst_receive(struct GNUNET_SERVER_MessageStreamTokenizer *mst, void *client_identity, 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.
void * libgnunet_plugin_transport_tcp_init(void *cls)
Entry point for the plugin.
#define PLUGIN_NAME
TcpAddressOptions
Bits in the options field of TCP addresses.
@ TCP_OPTIONS_NONE
No bits set.
@ TCP_OPTIONS_TCP_STEALTH
Enable TCP Stealth-style port knocking.
@ TCP_OPTIONS_RESERVED
See HTTP_OPTIONS_VERIFY_CERTIFICATE.
static struct GNUNET_ATS_Session * lookup_session_by_client(struct Plugin *plugin, struct GNUNET_SERVER_Client *client)
Find the session handle for the given client.
static int tcp_plugin_disconnect_session(void *cls, struct GNUNET_ATS_Session *session)
Functions with this signature are called whenever we need to close a session due to a disconnect or f...
static void handle_tcp_nat_probe(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message)
We've received a nat probe from this peer via TCP.
static void tcp_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.
void GNUNET_SERVER_client_keep(struct GNUNET_SERVER_Client *client)
Notify the server that the given client handle should be kept (keeps the connection up if possible,...
struct GNUNET_SERVER_MessageStreamTokenizer * GNUNET_SERVER_mst_create(GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
void GNUNET_SERVER_client_drop(struct GNUNET_SERVER_Client *client)
Notify the server that the given client handle is no longer required.
#define GNUNET_SERVER_client_get_user_context(client, type)
Return user context associated with the given client.
static void session_timeout(void *cls)
Session was idle for too long, so disconnect it.
void(* LEGACY_SERVICE_Main)(void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg)
Function called by the service's run method to run service-specific setup code.
static void handle_tcp_welcome(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message)
We've received a welcome from this peer via TCP.
void(* GNUNET_SERVER_MstDestroyCallback)(void *cls, void *mst)
Signature of a function to destroy a custom tokenizer.
static int tcp_plugin_check_address(void *cls, const void *addr, size_t addrlen)
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
static void tcp_plugin_update_session_timeout(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Session *session)
Function that will be called whenever the transport service wants to notify the plugin that a session...
static void try_connection_reversal(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Function called by the NAT subsystem suggesting another peer wants to connect to us via connection re...
static struct GNUNET_ATS_Session * tcp_plugin_get_session(void *cls, const struct GNUNET_HELLO_Address *address)
Create a new session to transmit data to the target This session will used to send data to this peer ...
static void tcp_plugin_setup_monitor(void *cls, GNUNET_TRANSPORT_SessionInfoCallback sic, void *sic_cls)
Begin monitoring sessions of a plugin.
static ssize_t tcp_plugin_send(void *cls, struct GNUNET_ATS_Session *session, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
Function that can be used by the transport service to transmit a message using the plugin.
static void delayed_done(void *cls)
Task to signal the server that we can continue receiving from the TCP client now.
#define NAT_TIMEOUT
How long until we give up on establishing an NAT connection? Must be > 4 RTT.
void GNUNET_SERVER_destroy(struct GNUNET_SERVER_Handle *server)
Free resources held by this server.
static unsigned int tcp_plugin_query_keepalive_factor(void *cls)
Function that is called to get the keepalive factor.
void * GNUNET_SERVER_client_get_user_context_(struct GNUNET_SERVER_Client *client, size_t size)
Return user context associated with the given client.
static void tcp_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
Function that can be called to force a disconnect from the specified neighbour.
void(* GNUNET_SERVER_DisconnectCallback)(void *cls, struct GNUNET_SERVER_Client *client)
Functions with this signature are called whenever a client is disconnected on the network level.
struct GNUNET_SERVER_Client * GNUNET_SERVER_connect_socket(struct GNUNET_SERVER_Handle *server, struct GNUNET_CONNECTION_Handle *connection)
Add a TCP socket-based connection to the set of handles managed by this server.
static enum GNUNET_NetworkType tcp_plugin_get_network_for_address(void *cls, const struct GNUNET_HELLO_Address *address)
Function obtain the network type for an address.
void GNUNET_SERVER_mst_destroy(struct GNUNET_SERVER_MessageStreamTokenizer *mst)
Destroys a tokenizer.
static size_t notify_send_probe(void *cls, size_t size, void *buf)
We can now send a probe message, copy into buffer to really send.
size_t(* GNUNET_CONNECTION_TransmitReadyNotify)(void *cls, size_t size, void *buf)
Function called to notify a client about the connection begin ready to queue more data.
static int session_disconnect_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
We have been asked to destroy all connections to a particular peer.
static void nat_connect_timeout(void *cls)
Task cleaning up a NAT connection attempt after timeout.
void(* GNUNET_SERVER_ConnectCallback)(void *cls, struct GNUNET_SERVER_Client *client)
Functions with this signature are called whenever a client is connected on the network level.
static int get_server_addresses(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, struct sockaddr ***addrs, socklen_t **addr_lens)
Get the list of addresses that a server for the given service should bind to.
static int tcp_plugin_string_to_address(void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added)
Function called to convert a string address to a binary address.
static struct GNUNET_ATS_Session * create_session(struct Plugin *plugin, const struct GNUNET_HELLO_Address *address, enum GNUNET_NetworkType scope, struct GNUNET_SERVER_Client *client, int is_nat)
Create a new session.
static void reschedule_session_timeout(struct GNUNET_ATS_Session *s)
Increment session timeout due to activity.
LEGACY_SERVICE_Options
Options for the service (bitmask).
@ LEGACY_SERVICE_OPTION_NONE
Use defaults.
@ LEGACY_SERVICE_OPTION_SOFT_SHUTDOWN
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
@ LEGACY_SERVICE_OPTION_MANUAL_SHUTDOWN
Do not trigger server shutdown on signal at all; instead, allow for the user to terminate the server ...
void(* GNUNET_CONNECTION_Receiver)(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback function for data received from the network.
static int session_lookup_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Look for a session by address.
static void append_port(void *cls, const char *hostname)
We are processing an address pretty printing request and finished the IP resolution (if applicable).
static void tcp_plugin_update_inbound_delay(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Session *session, struct GNUNET_TIME_Relative delay)
Function that will be called whenever the transport service wants to notify the plugin that the inbou...
int(* GNUNET_SERVER_MstReceiveCallback)(void *cls, void *mst, struct GNUNET_SERVER_Client *client, const char *buf, size_t size, int purge, int one_shot)
Signature of a function to receive data for a custom tokenizer.
int(* GNUNET_CONNECTION_AccessCheck)(void *cls, const struct GNUNET_CONNECTION_Credentials *ucred, const struct sockaddr *addr, socklen_t addrlen)
Function to call for access control checks.
void GNUNET_CONNECTION_destroy(struct GNUNET_CONNECTION_Handle *connection)
Close the connection and free associated resources.
#define GNUNET_SERVER_client_set_user_context(client, value)
Set user context to be associated with the given client.
void GNUNET_SERVER_suspend(struct GNUNET_SERVER_Handle *server)
Suspend accepting connections from the listen socket temporarily.
void LEGACY_SERVICE_stop(struct LEGACY_SERVICE_Context *srv)
Stops a service that was started with GNUNET_SERVICE_start().
static size_t do_transmit(void *cls, size_t size, void *buf)
Function called to notify a client about the socket being ready to queue more data.
void(* GNUNET_SERVER_MessageCallback)(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message)
Functions with this signature are called whenever a message is received.
static void process_pending_messages(struct GNUNET_ATS_Session *session)
If we have pending messages, ask the server to transmit them (schedule the respective tasks,...
static void tcp_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.
void GNUNET_SERVER_client_disconnect(struct GNUNET_SERVER_Client *client)
Ask the server to disconnect from the given client.
#define LOG(kind,...)
static enum GNUNET_NetworkType tcp_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
Function obtain the network type for a session.
static void disconnect_notify(void *cls, struct GNUNET_SERVER_Client *client)
Function called whenever a peer is disconnected on the "SERVER" level.
struct GNUNET_SERVER_TransmitHandle * GNUNET_SERVER_notify_transmit_ready(struct GNUNET_SERVER_Client *client, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_TransmitReadyNotify callback, void *callback_cls)
Notify us when the server has enough space to transmit a message of the given size to the given clien...
static void connect_notify(void *cls, struct GNUNET_SERVER_Client *client)
Function called whenever a peer is connected on the "SERVER" level.
static int send_session_info_iter(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Return information about the given session to the monitor callback.
static void 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.
void * libgnunet_plugin_transport_tcp_done(void *cls)
Exit point from the plugin.
void GNUNET_SERVER_resume(struct GNUNET_SERVER_Handle *server)
Resume accepting connections from the listen socket.
void GNUNET_SERVER_notify_transmit_ready_cancel(struct GNUNET_SERVER_TransmitHandle *th)
Abort transmission request.
static enum GNUNET_NetworkType scope
Which network scope do we belong to?
Closure for session_lookup_it().
struct GNUNET_ATS_Session * result
Where to store the session (if we found it).
const struct GNUNET_HELLO_Address * address
Address we are looking for.
Session handle for connections.
struct GNUNET_PeerIdentity target
To whom are we talking to.
struct Plugin * plugin
Pointer to the global plugin struct.
unsigned int msgs_in_queue
Number of messages waiting for transmission to this peer.
int is_nat
Was this session created using NAT traversal?
struct GNUNET_SERVER_Client * client
The client (used to identify this connection)
struct PendingMessage * pending_messages_tail
Messages currently pending for transmission to this peer, if any.
struct GNUNET_SCHEDULER_Task * nat_connection_timeout
Task cleaning up a NAT client connection establishment attempt;.
struct GNUNET_TIME_Absolute timeout
When does this session time out.
struct GNUNET_SERVER_TransmitHandle * transmit_handle
Handle for pending transmission request.
struct PendingMessage * pending_messages_head
Messages currently pending for transmission to this peer, if any.
struct GNUNET_TIME_Absolute receive_delay
When will we continue to read from the socket? (used to enforce inbound quota).
struct GNUNET_HELLO_Address * address
Address.
enum GNUNET_NetworkType scope
ATS network type.
unsigned long long bytes_in_queue
Number of bytes waiting for transmission to this peer.
int expecting_welcome
Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO)
struct GNUNET_TIME_Absolute last_activity
Last activity on this connection.
struct GNUNET_SCHEDULER_Task * receive_delay_task
ID of task used to delay receiving more to throttle sender.
struct GNUNET_SCHEDULER_Task * timeout_task
Session timeout task.
void * cls
Closure for all of the callbacks.
Credentials for UNIX domain sockets.
uid_t uid
UID of the other end of the connection.
gid_t gid
GID of the other end of the connection.
handle for a network connection
struct GNUNET_NETWORK_Handle * sock
Underlying OS's socket, set to NULL after fatal errors.
Internal representation of the hash map.
void * cls
Closure to use for callbacks.
An address for communicating with a peer.
size_t address_length
Number of bytes in address.
const void * address
Binary representation of the address (plugin-specific).
Header for all communications.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Handle for active NAT registrations.
Definition: nat_api.c:72
handle to a socket
Definition: network.c:54
socklen_t addrlen
Number of bytes in addr.
Definition: network.c:70
The identity of the host (wraps the signing key of the peer).
Handle to a request given to the resolver.
Definition: resolver_api.c:104
Entry in list of pending tasks.
Definition: scheduler.c:136
handle for a client of the server
struct GNUNET_CONNECTION_Handle * connection
Client closure for callbacks.
void * mst
Processing of incoming data.
struct GNUNET_SERVER_Handle * server
Server that this client belongs to.
handle for a server
uint16_t type
Type of the message this handler covers.
GNUNET_SERVER_MessageCallback callback
Function to call for messages of "type".
void * callback_cls
Closure argument for callback.
uint16_t expected_size
Expected size of messages of this type.
Handle to a message stream tokenizer.
GNUNET_SERVER_MessageTokenizerCallback cb
Function to call on completed messages.
Handle server returns for aborting transmission to a client.
void * callback_cls
Closure for callback.
GNUNET_CONNECTION_TransmitReadyNotify callback
Function to call to get the message.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
The transport service will pass a pointer to a struct of this type as the first and only argument to ...
void * cls
Closure for the various callbacks.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
void * cls
Closure for all of the callbacks.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
GNUNET_TRANSPORT_UpdateInboundDelay update_inbound_delay
Function that will be called whenever the transport service wants to notify the plugin that the inbou...
GNUNET_TRANSPORT_SessionMonitorSetup setup_monitor
Function to monitor the sessions managed by the plugin.
GNUNET_TRANSPORT_DisconnectPeerFunction disconnect_peer
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
GNUNET_TRANSPORT_GetNetworkTypeForAddress get_network_for_address
Function to obtain the network type for an address.
GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
GNUNET_TRANSPORT_QueryKeepaliveFactorFunction query_keepalive_factor
Function that is used to query keepalive factor.
GNUNET_TRANSPORT_AddressPrettyPrinter address_pretty_printer
Function to pretty-print addresses.
GNUNET_TRANSPORT_AddressToString address_to_string
Function that will be called to convert a binary address to a string (numeric conversion only).
GNUNET_TRANSPORT_GetNetworkType get_network
Function to obtain the network type for a session.
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
GNUNET_TRANSPORT_CheckAddress check_address
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
GNUNET_TRANSPORT_StringToAddress string_to_address
Function that will be called to convert a string address to binary (numeric conversion only).
GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout
Function that will be called whenever the transport service wants to notify the plugin that a session...
Information about a plugin's session.
Network format for IPv4 addresses.
uint16_t t4_port
Port number, in network byte order.
uint32_t ipv4_addr
IPv4 address, in network byte order.
uint32_t options
Optional options and flags for this address, see enum TcpAddressOptions
Network format for IPv6 addresses.
uint32_t options
Optional flags for this address see enum TcpAddressOptions
struct in6_addr ipv6_addr
IPv6 address.
uint16_t t6_port
Port number, in network byte order.
Context for "service_task".
List containing all messages that are yet to be send.
struct TransportClient * client
Client that issued the transmission request, if pmt is PMT_CORE.
size_t message_size
So that the gnunet-service-transport can group messages together, these pending messages need to acce...
struct PendingMessage * prev
This is a doubly-linked list.
struct PendingMessage * next
DLL next, prev.
const char * msg
The pending message.
GNUNET_TRANSPORT_TransmitContinuation transmit_cont
Continuation function to call once the message has been sent.
struct GNUNET_TIME_Absolute timeout
At what time should we give up on the transmission (and no longer retry)?
void * transmit_cont_cls
Closure for transmit_cont.
Handle for a plugin.
Definition: block.c:38
struct GNUNET_CONTAINER_MultiPeerMap * sessionmap
Map from peer identities to sessions for the given peer.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
unsigned long long cur_connections
How many more TCP sessions do we have right now?
void * sic_cls
Closure for sic.
struct GNUNET_CONNECTION_Handle * lsock
The listen socket.
struct GNUNET_SERVER_MessageHandler * handlers
Copy of the handler array where the closures are set to this struct's instance.
uint16_t adv_port
Port that the user said we would have visible to the rest of the world.
struct GNUNET_SCHEDULER_Task * address_update_task
ID of task used to update our addresses when one expires.
struct TCPProbeContext * probe_head
List of active TCP probes.
struct PrettyPrinterContext * ppc_dll_head
Running pretty printers: head.
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
unsigned long long max_connections
How many more TCP sessions are we allowed to open right now?
struct LEGACY_SERVICE_Context * service
Handle to the network service.
struct GNUNET_NAT_Handle * nat
NAT handle & address management.
uint32_t myoptions
Address options.
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.
struct GNUNET_SERVER_Handle * server
Handle to the server for this service.
struct TCPProbeContext * probe_tail
List of active TCP probes.
struct WelcomeMessage my_welcome
Welcome message used by this peer.
uint16_t open_port
Port that we are actually listening on.
struct PrettyPrinterContext * ppc_dll_tail
Running pretty printers: tail.
struct GNUNET_CONTAINER_MultiPeerMap * nat_wait_conns
Map of peers we have tried to contact behind a NAT.
Closure for append_port().
struct GNUNET_RESOLVER_RequestHandle * resolver_handle
Resolver handle.
struct Plugin * plugin
Our plugin.
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task.
uint16_t port
Port to add after the IP address.
void * asc_cls
Clsoure for asc.
GNUNET_TRANSPORT_AddressStringCallback asc
Function to call with the result.
uint32_t options
Address options.
struct PrettyPrinterContext * prev
DLL.
struct PrettyPrinterContext * next
DLL.
Context for sending a NAT probe via TCP.
struct TCPProbeContext * prev
Active probes are kept in a DLL.
struct TCPProbeContext * next
Active probes are kept in a DLL.
struct GNUNET_CONNECTION_Handle * sock
Probe connection.
struct TCP_NAT_ProbeMessage message
Message to be sent.
struct GNUNET_CONNECTION_TransmitHandle * transmit_handle
Handle to the transmission.
struct Plugin * plugin
Transport plugin handle.
Basically a WELCOME message, but with the purpose of giving the waiting peer a client handle to use.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE.
struct GNUNET_PeerIdentity clientIdentity
Identity of the sender of the message.
Initial handshake message for a session.
struct GNUNET_PeerIdentity clientIdentity
Identity of the node connecting (TCP client)
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
struct GNUNET_CONNECTION_TransmitHandle * GNUNET_CONNECTION_notify_transmit_ready(struct GNUNET_CONNECTION_Handle *connection, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls)
Ask the connection to call us once the specified number of bytes are free in the transmission buffer.
struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_connect_socket(struct GNUNET_NETWORK_Handle *s, const struct sockaddr *serv_addr, socklen_t addrlen)
Create a connection handle by (asynchronously) connecting to a host.
struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_sockaddr(int af_family, const struct sockaddr *serv_addr, socklen_t addrlen)
Create a connection handle by creating a socket and (asynchronously) connecting to a host.
void GNUNET_SERVER_add_handlers(struct GNUNET_SERVER_Handle *server, const struct GNUNET_SERVER_MessageHandler *handlers)
Add additional handlers to an existing server.
void GNUNET_SERVER_disable_receive_done_warning(struct GNUNET_SERVER_Client *client)
Disable the warning the server issues if a message is not acknowledged in a timely fashion.
void GNUNET_SERVER_connect_notify(struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_ConnectCallback callback, void *callback_cls)
Ask the server to notify us whenever a client connects.
void GNUNET_SERVER_client_set_timeout(struct GNUNET_SERVER_Client *client, struct GNUNET_TIME_Relative timeout)
Change the timeout for a particular client.
struct GNUNET_SERVER_Handle * GNUNET_SERVER_create_with_sockets(GNUNET_CONNECTION_AccessCheck access_cb, void *access_cb_cls, struct GNUNET_NETWORK_Handle **lsocks, struct GNUNET_TIME_Relative idle_timeout, int require_found)
Create a new server.
void GNUNET_SERVER_receive_done(struct GNUNET_SERVER_Client *client, int success)
Resume receiving from this client, we are done processing the current request.
int GNUNET_SERVER_client_get_address(struct GNUNET_SERVER_Client *client, void **addr, size_t *addrlen)
Obtain the network address of the other party.
void GNUNET_SERVER_disconnect_notify(struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_DisconnectCallback callback, void *callback_cls)
Ask the server to notify us whenever a client disconnects.
struct GNUNET_SERVER_Handle * LEGACY_SERVICE_get_server(struct LEGACY_SERVICE_Context *ctx)
Obtain the server used by a service.
struct GNUNET_NETWORK_Handle *const * LEGACY_SERVICE_get_listen_sockets(struct LEGACY_SERVICE_Context *ctx)
Get the NULL-terminated array of listen sockets for this service.
struct LEGACY_SERVICE_Context * LEGACY_SERVICE_start(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, enum LEGACY_SERVICE_Options options)
Run a service startup sequence within an existing initialized system.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
common internal definitions for transport service