GNUnet  0.10.x
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 
89 
100 typedef size_t
102  size_t size,
103  void *buf);
104 
109 {
113  uid_t uid;
114 
118  gid_t gid;
119 };
120 
121 
130 typedef void
132  struct GNUNET_SERVER_Client *client);
133 
134 
142 typedef void
144  struct GNUNET_SERVER_Client *client);
145 
146 
147 
148 
159 typedef int
161  const struct
163  ucred,
164  const struct sockaddr * addr,
165  socklen_t addrlen);
166 
179 typedef void
180 (*GNUNET_CONNECTION_Receiver) (void *cls, const void *buf,
181  size_t available,
182  const struct sockaddr * addr,
183  socklen_t addrlen, int errCode);
184 
185 
186 
194 void
196 
197 
205 typedef void*
206 (*GNUNET_SERVER_MstCreateCallback) (void *cls,
207  struct GNUNET_SERVER_Client *client);
208 
209 
216 typedef void
218  void *mst);
219 
236 typedef int
238  struct GNUNET_SERVER_Client *client,
239  const char *buf,
240  size_t size,
241  int purge,
242  int one_shot);
251 typedef void
253  struct GNUNET_SERVER_Client *client,
254  const struct GNUNET_MessageHeader *message);
255 
261 {
266 
271 
275  uint16_t type;
276 
283  uint16_t expected_size;
284 
285 };
286 
287 
292 {
298 
305 
311 };
312 
313 
314 
323 void
325 
334 void *
336  size_t size);
337 
338 
351 typedef int
353  void *client,
354  const struct GNUNET_MessageHeader *message);
355 
356 
366  void *cb_cls);
367 
384 int
386  void *client_identity,
387  const char *buf, size_t size,
388  int purge, int one_shot);
389 
390 
391 
397 void
399 
400 
409 void
411  void *ptr,
412  size_t size);
420 #define GNUNET_SERVER_client_get_user_context(client,type) \
421  (type *) GNUNET_SERVER_client_get_user_context_ (client, sizeof (type))
422 
429 #define GNUNET_SERVER_client_set_user_context(client,value) \
430  GNUNET_SERVER_client_set_user_context_ (client, value, sizeof (*value))
431 
432 
433 
451  size_t size,
454  void *callback_cls);
455 
461 void
463 
464 
465 
466 
474 void
476 
477 
486 void
488 
489 
498 typedef void
499 (*LEGACY_SERVICE_Main) (void *cls,
500  struct GNUNET_SERVER_Handle *server,
501  const struct GNUNET_CONFIGURATION_Handle *cfg);
502 
503 
504 
511 void
513 
531  size_t size,
534  void *callback_cls);
535 
536 
548 struct GNUNET_SERVER_Client *
551 
552 
558 void
560 
566 void
568 
569 
570 
571 
572 #include "tcp_connection_legacy.c"
573 #include "tcp_server_mst_legacy.c"
574 #include "tcp_server_legacy.c"
575 #include "tcp_service_legacy.c"
576 
578 
583 {
587  struct GNUNET_MessageHeader header;
588 
592  struct GNUNET_PeerIdentity clientIdentity;
593 
594 };
595 
601 {
605  struct GNUNET_MessageHeader header;
606 
610  struct GNUNET_PeerIdentity clientIdentity;
611 
612 };
614 
619 {
620 
625 
630 
635 
639  struct TCP_NAT_ProbeMessage message;
640 
645 
649  struct Plugin *plugin;
650 };
651 
656 {
657 
662 
667 
672 };
673 
675 
680 {
686 
690  uint32_t ipv4_addr GNUNET_PACKED;
691 
695  uint16_t t4_port GNUNET_PACKED;
696 
697 };
698 
703 {
709 
713  struct in6_addr ipv6_addr GNUNET_PACKED;
714 
718  uint16_t t6_port GNUNET_PACKED;
719 
720 };
722 
726 struct Plugin;
727 
732 struct PendingMessage
733 {
734 
738  struct PendingMessage *next;
739 
743  struct PendingMessage *prev;
744 
748  const char *msg;
749 
756 
761 
766 
772  size_t message_size;
773 
774 };
775 
779 struct GNUNET_ATS_Session
780 {
785  struct GNUNET_PeerIdentity target;
786 
790  struct Plugin *plugin;
791 
796 
801 
807 
813 
818 
823 
828 
833 
838 
843  struct GNUNET_TIME_Absolute receive_delay;
844 
849  struct GNUNET_TIME_Absolute last_activity;
850 
854  unsigned long long bytes_in_queue;
855 
859  unsigned int msgs_in_queue;
860 
865 
870 
874  int is_nat;
875 
876 };
877 
878 
884 {
888  struct PrettyPrinterContext *next;
889 
893  struct PrettyPrinterContext *prev;
894 
898  struct Plugin *plugin;
899 
904 
908  struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
909 
914 
918  void *asc_cls;
919 
923  int ipv6;
924 
928  uint32_t options;
929 
933  uint16_t port;
934 };
935 
936 
940 struct Plugin
941 {
946 
951 
955  struct GNUNET_NAT_Handle *nat;
956 
961 
966 
971 
977 
982 
987 
992 
997 
1001  void *sic_cls;
1002 
1007 
1012 
1017 
1021  struct WelcomeMessage my_welcome;
1022 
1026  unsigned long long max_connections;
1027 
1031  unsigned long long cur_connections;
1032 
1036  uint32_t myoptions;
1037 
1041  uint16_t open_port;
1042 
1047  uint16_t adv_port;
1048 
1049 };
1050 
1051 
1072 static int
1074  const struct GNUNET_CONFIGURATION_Handle *cfg,
1075  struct sockaddr ***addrs,
1076  socklen_t ** addr_lens)
1077 {
1078  int disablev6;
1079  struct GNUNET_NETWORK_Handle *desc;
1080  unsigned long long port;
1081  char *unixpath;
1082  struct addrinfo hints;
1083  struct addrinfo *res;
1084  struct addrinfo *pos;
1085  struct addrinfo *next;
1086  unsigned int i;
1087  int resi;
1088  int ret;
1089  int abstract;
1090  struct sockaddr **saddrs;
1091  socklen_t *saddrlens;
1092  char *hostname;
1093 
1094  *addrs = NULL;
1095  *addr_lens = NULL;
1096  desc = NULL;
1097  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
1098  {
1099  if (GNUNET_SYSERR ==
1100  (disablev6 =
1101  GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
1102  return GNUNET_SYSERR;
1103  }
1104  else
1105  disablev6 = GNUNET_NO;
1106 
1107  if (! disablev6)
1108  {
1109  /* probe IPv6 support */
1110  desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
1111  if (NULL == desc)
1112  {
1113  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1114  (EACCES == errno))
1115  {
1117  return GNUNET_SYSERR;
1118  }
1120  _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
1121  service_name, STRERROR (errno));
1122  disablev6 = GNUNET_YES;
1123  }
1124  else
1125  {
1127  desc = NULL;
1128  }
1129  }
1130 
1131  port = 0;
1132  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
1133  {
1134  if (GNUNET_OK !=
1135  GNUNET_CONFIGURATION_get_value_number (cfg, service_name,
1136  "PORT", &port))
1137  {
1139  _("Require valid port number for service `%s' in configuration!\n"),
1140  service_name);
1141  }
1142  if (port > 65535)
1143  {
1145  _("Require valid port number for service `%s' in configuration!\n"),
1146  service_name);
1147  return GNUNET_SYSERR;
1148  }
1149  }
1150 
1151  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
1152  {
1154  GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
1155  "BINDTO", &hostname));
1156  }
1157  else
1158  hostname = NULL;
1159 
1160  unixpath = NULL;
1161  abstract = GNUNET_NO;
1162 #ifdef AF_UNIX
1163  if ((GNUNET_YES ==
1164  GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
1165  (GNUNET_OK ==
1166  GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
1167  &unixpath)) &&
1168  (0 < strlen (unixpath)))
1169  {
1170  /* probe UNIX support */
1171  struct sockaddr_un s_un;
1172 
1173  if (strlen (unixpath) >= sizeof (s_un.sun_path))
1174  {
1176  _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
1177  (unsigned long long) sizeof (s_un.sun_path));
1178  unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1180  _("Using `%s' instead\n"),
1181  unixpath);
1182  }
1183 #ifdef LINUX
1184  abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
1185  "TESTING",
1186  "USE_ABSTRACT_SOCKETS");
1187  if (GNUNET_SYSERR == abstract)
1188  abstract = GNUNET_NO;
1189 #endif
1190  if ((GNUNET_YES != abstract)
1191  && (GNUNET_OK !=
1194  "mkdir",
1195  unixpath);
1196  }
1197  if (NULL != unixpath)
1198  {
1199  desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
1200  if (NULL == desc)
1201  {
1202  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1203  (EACCES == errno))
1204  {
1206  GNUNET_free_non_null (hostname);
1207  GNUNET_free (unixpath);
1208  return GNUNET_SYSERR;
1209  }
1211  _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1212  service_name,
1213  STRERROR (errno));
1214  GNUNET_free (unixpath);
1215  unixpath = NULL;
1216  }
1217  else
1218  {
1220  desc = NULL;
1221  }
1222  }
1223 #endif
1224 
1225  if ((0 == port) && (NULL == unixpath))
1226  {
1228  _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1229  service_name);
1230  GNUNET_free_non_null (hostname);
1231  return GNUNET_SYSERR;
1232  }
1233  if (0 == port)
1234  {
1235  saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
1236  saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
1237  add_unixpath (saddrs, saddrlens, unixpath, abstract);
1238  GNUNET_free_non_null (unixpath);
1239  GNUNET_free_non_null (hostname);
1240  *addrs = saddrs;
1241  *addr_lens = saddrlens;
1242  return 1;
1243  }
1244 
1245  if (NULL != hostname)
1246  {
1248  "Resolving `%s' since that is where `%s' will bind to.\n",
1249  hostname,
1250  service_name);
1251  memset (&hints, 0, sizeof (struct addrinfo));
1252  if (disablev6)
1253  hints.ai_family = AF_INET;
1254  hints.ai_protocol = IPPROTO_TCP;
1255  if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1256  (NULL == res))
1257  {
1259  _("Failed to resolve `%s': %s\n"),
1260  hostname,
1261  gai_strerror (ret));
1262  GNUNET_free (hostname);
1263  GNUNET_free_non_null (unixpath);
1264  return GNUNET_SYSERR;
1265  }
1266  next = res;
1267  i = 0;
1268  while (NULL != (pos = next))
1269  {
1270  next = pos->ai_next;
1271  if ((disablev6) && (pos->ai_family == AF_INET6))
1272  continue;
1273  i++;
1274  }
1275  if (0 == i)
1276  {
1278  _("Failed to find %saddress for `%s'.\n"),
1279  disablev6 ? "IPv4 " : "",
1280  hostname);
1281  freeaddrinfo (res);
1282  GNUNET_free (hostname);
1283  GNUNET_free_non_null (unixpath);
1284  return GNUNET_SYSERR;
1285  }
1286  resi = i;
1287  if (NULL != unixpath)
1288  resi++;
1289  saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1290  saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1291  i = 0;
1292  if (NULL != unixpath)
1293  {
1294  add_unixpath (saddrs, saddrlens, unixpath, abstract);
1295  i++;
1296  }
1297  next = res;
1298  while (NULL != (pos = next))
1299  {
1300  next = pos->ai_next;
1301  if ((disablev6) && (AF_INET6 == pos->ai_family))
1302  continue;
1303  if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1304  continue; /* not TCP */
1305  if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1306  continue; /* huh? */
1307  LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
1308  service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1309  if (AF_INET == pos->ai_family)
1310  {
1311  GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
1312  saddrlens[i] = pos->ai_addrlen;
1313  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1314  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1315  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1316  }
1317  else
1318  {
1319  GNUNET_assert (AF_INET6 == pos->ai_family);
1320  GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
1321  saddrlens[i] = pos->ai_addrlen;
1322  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1323  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1324  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1325  }
1326  i++;
1327  }
1328  GNUNET_free (hostname);
1329  freeaddrinfo (res);
1330  resi = i;
1331  }
1332  else
1333  {
1334  /* will bind against everything, just set port */
1335  if (disablev6)
1336  {
1337  /* V4-only */
1338  resi = 1;
1339  if (NULL != unixpath)
1340  resi++;
1341  i = 0;
1342  saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1343  saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1344  if (NULL != unixpath)
1345  {
1346  add_unixpath (saddrs, saddrlens, unixpath, abstract);
1347  i++;
1348  }
1349  saddrlens[i] = sizeof (struct sockaddr_in);
1350  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1351 #if HAVE_SOCKADDR_IN_SIN_LEN
1352  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1353 #endif
1354  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1355  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1356  }
1357  else
1358  {
1359  /* dual stack */
1360  resi = 2;
1361  if (NULL != unixpath)
1362  resi++;
1363  saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1364  saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1365  i = 0;
1366  if (NULL != unixpath)
1367  {
1368  add_unixpath (saddrs, saddrlens, unixpath, abstract);
1369  i++;
1370  }
1371  saddrlens[i] = sizeof (struct sockaddr_in6);
1372  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1373 #if HAVE_SOCKADDR_IN_SIN_LEN
1374  ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1375 #endif
1376  ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1377  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1378  i++;
1379  saddrlens[i] = sizeof (struct sockaddr_in);
1380  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1381 #if HAVE_SOCKADDR_IN_SIN_LEN
1382  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1383 #endif
1384  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1385  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1386  }
1387  }
1388  GNUNET_free_non_null (unixpath);
1389  *addrs = saddrs;
1390  *addr_lens = saddrlens;
1391  return resi;
1392 }
1393 /* end ancient copy-and-paste */
1394 
1395 
1404 static void
1406  struct GNUNET_ATS_Session *session,
1408 {
1409  struct GNUNET_TRANSPORT_SessionInfo info;
1410 
1411  if (NULL == plugin->sic)
1412  return;
1413  memset (&info, 0, sizeof (info));
1414  info.state = state;
1417  info.num_msg_pending = session->msgs_in_queue;
1418  info.num_bytes_pending = session->bytes_in_queue;
1419  if (NULL != session->receive_delay_task)
1420  info.receive_delay = session->receive_delay;
1421  info.session_timeout = session->timeout;
1422  info.address = session->address;
1423  plugin->sic (plugin->sic_cls,
1424  session,
1425  &info);
1426 }
1427 
1428 
1441 static void
1443  void **app_ctx,
1444  int add_remove,
1446  const struct sockaddr *addr,
1447  socklen_t addrlen)
1448 {
1449  struct Plugin *plugin = cls;
1450  struct GNUNET_HELLO_Address *address;
1451  struct IPv4TcpAddress t4;
1452  struct IPv6TcpAddress t6;
1453  void *arg;
1454  size_t args;
1455 
1456  (void) app_ctx;
1458  "NAT notification to %s address `%s'\n",
1459  (GNUNET_YES == add_remove) ? "add" : "remove",
1460  GNUNET_a2s (addr, addrlen));
1461  /* convert 'addr' to our internal format */
1462  switch (addr->sa_family)
1463  {
1464  case AF_INET:
1465  GNUNET_assert(addrlen == sizeof(struct sockaddr_in));
1466  memset (&t4, 0, sizeof(t4));
1467  t4.options = htonl (plugin->myoptions);
1468  t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1469  t4.t4_port = ((struct sockaddr_in *) addr)->sin_port;
1470  arg = &t4;
1471  args = sizeof (t4);
1472  break;
1473  case AF_INET6:
1474  if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
1475  {
1476  /* skip link local, we don't allow them in
1477  #tcp_plugin_check_address() */
1478  return;
1479  }
1480  GNUNET_assert(addrlen == sizeof(struct sockaddr_in6));
1481  memset (&t6, 0, sizeof(t6));
1482  GNUNET_memcpy (&t6.ipv6_addr,
1483  &((struct sockaddr_in6 *) addr)->sin6_addr,
1484  sizeof(struct in6_addr));
1485  t6.options = htonl (plugin->myoptions);
1486  t6.t6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
1487  arg = &t6;
1488  args = sizeof (t6);
1489  break;
1490  default:
1491  GNUNET_break(0);
1492  return;
1493  }
1494  /* modify our published address list */
1495  GNUNET_assert ((args == sizeof (struct IPv4TcpAddress)) ||
1496  (args == sizeof (struct IPv6TcpAddress)));
1497  /* TODO: use 'ac' here in the future... */
1498  address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1499  PLUGIN_NAME,
1500  arg,
1501  args,
1503  plugin->env->notify_address (plugin->env->cls,
1504  add_remove,
1505  address);
1506  GNUNET_HELLO_address_free (address);
1507 }
1508 
1509 
1521 static const char *
1523  const void *addr,
1524  size_t addrlen)
1525 {
1526  static char rbuf[INET6_ADDRSTRLEN + 12];
1527  char buf[INET6_ADDRSTRLEN];
1528  const void *sb;
1529  struct in_addr a4;
1530  struct in6_addr a6;
1531  const struct IPv4TcpAddress *t4;
1532  const struct IPv6TcpAddress *t6;
1533  int af;
1534  uint16_t port;
1535  uint32_t options;
1536 
1537  switch (addrlen)
1538  {
1539  case sizeof(struct IPv6TcpAddress):
1540  t6 = addr;
1541  af = AF_INET6;
1542  port = ntohs (t6->t6_port);
1543  options = ntohl (t6->options);
1544  GNUNET_memcpy (&a6, &t6->ipv6_addr, sizeof(a6));
1545  sb = &a6;
1546  break;
1547  case sizeof(struct IPv4TcpAddress):
1548  t4 = addr;
1549  af = AF_INET;
1550  port = ntohs (t4->t4_port);
1551  options = ntohl (t4->options);
1552  GNUNET_memcpy (&a4, &t4->ipv4_addr, sizeof(a4));
1553  sb = &a4;
1554  break;
1555  default:
1556  LOG (GNUNET_ERROR_TYPE_WARNING,
1557  _("Unexpected address length: %u bytes\n"),
1558  (unsigned int) addrlen);
1559  return NULL ;
1560  }
1561  if (NULL == inet_ntop (af, sb, buf, INET6_ADDRSTRLEN))
1562  {
1564  "inet_ntop");
1565  return NULL ;
1566  }
1567  GNUNET_snprintf (rbuf, sizeof(rbuf),
1568  (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u",
1569  PLUGIN_NAME,
1570  options,
1571  buf,
1572  port);
1573  return rbuf;
1574 }
1575 
1576 
1589 static int
1591  const char *addr,
1592  uint16_t addrlen,
1593  void **buf,
1594  size_t *added)
1595 {
1596  struct sockaddr_storage socket_address;
1597  char *address;
1598  char *plugin;
1599  char *optionstr;
1600  uint32_t options;
1601 
1602  /* Format tcp.options.address:port */
1603  address = NULL;
1604  plugin = NULL;
1605  optionstr = NULL;
1606  if ((NULL == addr) || (0 == addrlen))
1607  {
1608  GNUNET_break(0);
1609  return GNUNET_SYSERR;
1610  }
1611  if ('\0' != addr[addrlen - 1])
1612  {
1613  GNUNET_break(0);
1614  return GNUNET_SYSERR;
1615  }
1616  if (strlen (addr) != addrlen - 1)
1617  {
1618  GNUNET_break(0);
1619  return GNUNET_SYSERR;
1620  }
1621  plugin = GNUNET_strdup (addr);
1622  optionstr = strchr (plugin, '.');
1623  if (NULL == optionstr)
1624  {
1625  GNUNET_break(0);
1626  GNUNET_free(plugin);
1627  return GNUNET_SYSERR;
1628  }
1629  optionstr[0] = '\0';
1630  optionstr++;
1631  options = atol (optionstr);
1632  address = strchr (optionstr, '.');
1633  if (NULL == address)
1634  {
1635  GNUNET_break(0);
1636  GNUNET_free(plugin);
1637  return GNUNET_SYSERR;
1638  }
1639  address[0] = '\0';
1640  address++;
1641 
1642  if (GNUNET_OK !=
1644  strlen (address),
1645  &socket_address))
1646  {
1647  GNUNET_break(0);
1648  GNUNET_free(plugin);
1649  return GNUNET_SYSERR;
1650  }
1651 
1652  GNUNET_free(plugin);
1653  switch (socket_address.ss_family)
1654  {
1655  case AF_INET:
1656  {
1657  struct IPv4TcpAddress *t4;
1658  struct sockaddr_in *in4 = (struct sockaddr_in *) &socket_address;
1659  t4 = GNUNET_new (struct IPv4TcpAddress);
1660  t4->options = htonl (options);
1661  t4->ipv4_addr = in4->sin_addr.s_addr;
1662  t4->t4_port = in4->sin_port;
1663  *buf = t4;
1664  *added = sizeof(struct IPv4TcpAddress);
1665  return GNUNET_OK;
1666  }
1667  case AF_INET6:
1668  {
1669  struct IPv6TcpAddress *t6;
1670  struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &socket_address;
1671  t6 = GNUNET_new (struct IPv6TcpAddress);
1672  t6->options = htonl (options);
1673  t6->ipv6_addr = in6->sin6_addr;
1674  t6->t6_port = in6->sin6_port;
1675  *buf = t6;
1676  *added = sizeof(struct IPv6TcpAddress);
1677  return GNUNET_OK;
1678  }
1679  default:
1680  return GNUNET_SYSERR;
1681  }
1682 }
1683 
1684 
1695 static struct GNUNET_ATS_Session *
1697  struct GNUNET_SERVER_Client *client)
1698 {
1700  struct GNUNET_ATS_Session);
1701 }
1702 
1703 
1713 static int
1715  struct GNUNET_ATS_Session *session)
1716 {
1717  struct Plugin *plugin = cls;
1718  struct PendingMessage *pm;
1719 
1721  "Disconnecting session of peer `%s' address `%s'\n",
1722  GNUNET_i2s (&session->target),
1724  session->address->address,
1725  session->address->address_length));
1726 
1727  if (NULL != session->timeout_task)
1728  {
1730  session->timeout_task = NULL;
1732  }
1733 
1734  if (GNUNET_YES ==
1736  &session->target,
1737  session))
1738  {
1739  GNUNET_STATISTICS_update (session->plugin->env->stats,
1740  gettext_noop ("# TCP sessions active"),
1741  -1,
1742  GNUNET_NO);
1743  }
1744  else
1745  {
1748  &session->target,
1749  session));
1750  }
1751  if (NULL != session->client)
1753  NULL);
1754 
1755  /* clean up state */
1756  if (NULL != session->transmit_handle)
1757  {
1759  session->transmit_handle = NULL;
1760  }
1761  session->plugin->env->session_end (session->plugin->env->cls,
1762  session->address,
1763  session);
1764 
1765  if (NULL != session->nat_connection_timeout)
1766  {
1768  session->nat_connection_timeout = NULL;
1769  }
1770 
1771  while (NULL != (pm = session->pending_messages_head))
1772  {
1774  (NULL != pm->transmit_cont)
1775  ? "Could not deliver message to `%s' at %s.\n"
1776  : "Could not deliver message to `%s' at %s, notifying.\n",
1777  GNUNET_i2s (&session->target),
1779  session->address->address,
1780  session->address->address_length));
1781  GNUNET_STATISTICS_update (session->plugin->env->stats,
1782  gettext_noop ("# bytes currently in TCP buffers"),
1783  -(int64_t) pm->message_size, GNUNET_NO);
1784  GNUNET_STATISTICS_update (session->plugin->env->stats,
1785  gettext_noop ("# bytes discarded by TCP (disconnect)"),
1786  pm->message_size,
1787  GNUNET_NO);
1789  session->pending_messages_tail,
1790  pm);
1791  GNUNET_assert (0 < session->msgs_in_queue);
1792  session->msgs_in_queue--;
1793  GNUNET_assert (pm->message_size <= session->bytes_in_queue);
1794  session->bytes_in_queue -= pm->message_size;
1795  if (NULL != pm->transmit_cont)
1797  &session->target,
1798  GNUNET_SYSERR,
1799  pm->message_size,
1800  0);
1801  GNUNET_free (pm);
1802  }
1803  GNUNET_assert (0 == session->msgs_in_queue);
1804  GNUNET_assert (0 == session->bytes_in_queue);
1805  notify_session_monitor (session->plugin,
1806  session,
1808 
1809  if (NULL != session->receive_delay_task)
1810  {
1812  session->receive_delay_task = NULL;
1813  }
1814  if (NULL != session->client)
1815  {
1817  session->client = NULL;
1818  }
1820  GNUNET_assert (NULL == session->transmit_handle);
1821  GNUNET_free (session);
1822  return GNUNET_OK;
1823 }
1824 
1825 
1834 static unsigned int
1836 {
1837  return 3;
1838 }
1839 
1840 
1846 static void
1847 session_timeout (void *cls)
1848 {
1849  struct GNUNET_ATS_Session *s = cls;
1850  struct GNUNET_TIME_Relative left;
1851 
1852  s->timeout_task = NULL;
1854  if (0 != left.rel_value_us)
1855  {
1856  /* not actually our turn yet, but let's at least update
1857  the monitor, it may think we're about to die ... */
1859  s,
1862  &session_timeout,
1863  s);
1864  return;
1865  }
1867  "Session %p was idle for %s, disconnecting\n",
1868  s,
1870  GNUNET_YES));
1871  /* call session destroy function */
1873  s);
1874 }
1875 
1876 
1882 static void
1884 {
1885  GNUNET_assert (NULL != s->timeout_task);
1887 }
1888 
1889 
1902 static struct GNUNET_ATS_Session *
1904  const struct GNUNET_HELLO_Address *address,
1906  struct GNUNET_SERVER_Client *client,
1907  int is_nat)
1908 {
1909  struct GNUNET_ATS_Session *session;
1910  struct PendingMessage *pm;
1911 
1912  if (GNUNET_YES != is_nat)
1913  GNUNET_assert (NULL != client);
1914  else
1915  GNUNET_assert (NULL == client);
1916 
1918  "Creating new session for peer `%s' at address %s\n",
1919  GNUNET_i2s (&address->peer),
1921  address->address,
1922  address->address_length));
1923  session = GNUNET_new (struct GNUNET_ATS_Session);
1925  session->plugin = plugin;
1926  session->is_nat = is_nat;
1927  if (NULL != client)
1928  {
1929  session->client = client;
1931  session);
1932  }
1933  session->address = GNUNET_HELLO_address_copy (address);
1934  session->target = address->peer;
1935  session->expecting_welcome = GNUNET_YES;
1936  session->scope = scope;
1937  pm = GNUNET_malloc (sizeof (struct PendingMessage) +
1938  sizeof (struct WelcomeMessage));
1939  pm->msg = (const char *) &pm[1];
1940  pm->message_size = sizeof(struct WelcomeMessage);
1941  GNUNET_memcpy (&pm[1],
1942  &plugin->my_welcome,
1943  sizeof(struct WelcomeMessage));
1945  GNUNET_STATISTICS_update (plugin->env->stats,
1946  gettext_noop ("# bytes currently in TCP buffers"),
1947  pm->message_size,
1948  GNUNET_NO);
1950  session->pending_messages_tail,
1951  pm);
1952  session->msgs_in_queue++;
1953  session->bytes_in_queue += pm->message_size;
1956  &session_timeout,
1957  session);
1958  notify_session_monitor (session->plugin,
1959  session,
1961  if (GNUNET_YES != is_nat)
1962  {
1963  GNUNET_STATISTICS_update (plugin->env->stats,
1964  gettext_noop ("# TCP sessions active"),
1965  1,
1966  GNUNET_NO);
1967  notify_session_monitor (session->plugin,
1968  session,
1970  }
1971  else
1972  {
1973  notify_session_monitor (session->plugin,
1974  session,
1976  }
1977  return session;
1978 }
1979 
1980 
1987 static void
1989 
1990 
2002 static size_t
2003 do_transmit (void *cls,
2004  size_t size,
2005  void *buf)
2006 {
2007  struct GNUNET_ATS_Session *session = cls;
2008  struct GNUNET_PeerIdentity pid;
2009  struct Plugin *plugin;
2010  struct PendingMessage *pos;
2011  struct PendingMessage *hd;
2012  struct PendingMessage *tl;
2013  struct GNUNET_TIME_Absolute now;
2014  char *cbuf;
2015  size_t ret;
2016 
2017  session->transmit_handle = NULL;
2018  plugin = session->plugin;
2019  if (NULL == buf)
2020  {
2022  "Timeout trying to transmit to peer `%s', discarding message queue.\n",
2023  GNUNET_i2s (&session->target));
2024  /* timeout; cancel all messages that have already expired */
2025  hd = NULL;
2026  tl = NULL;
2027  ret = 0;
2028  now = GNUNET_TIME_absolute_get ();
2029  while ( (NULL != (pos = session->pending_messages_head)) &&
2030  (pos->timeout.abs_value_us <= now.abs_value_us) )
2031  {
2033  session->pending_messages_tail,
2034  pos);
2035  GNUNET_assert (0 < session->msgs_in_queue);
2036  session->msgs_in_queue--;
2037  GNUNET_assert (pos->message_size <= session->bytes_in_queue);
2038  session->bytes_in_queue -= pos->message_size;
2040  "Failed to transmit %u byte message to `%s'.\n",
2041  pos->message_size,
2042  GNUNET_i2s (&session->target));
2043  ret += pos->message_size;
2045  tl,
2046  tl,
2047  pos);
2048  }
2049  /* do this call before callbacks (so that if callbacks destroy
2050  * session, they have a chance to cancel actions done by this
2051  * call) */
2052  process_pending_messages (session);
2053  pid = session->target;
2054  /* no do callbacks and do not use session again since
2055  * the callbacks may abort the session */
2056  while (NULL != (pos = hd))
2057  {
2059  tl,
2060  pos);
2061  if (NULL != pos->transmit_cont)
2062  pos->transmit_cont (pos->transmit_cont_cls,
2063  &pid,
2064  GNUNET_SYSERR,
2065  pos->message_size,
2066  0);
2067  GNUNET_free (pos);
2068  }
2069  GNUNET_STATISTICS_update (plugin->env->stats,
2070  gettext_noop ("# bytes currently in TCP buffers"), -(int64_t) ret,
2071  GNUNET_NO);
2072  GNUNET_STATISTICS_update (plugin->env->stats,
2073  gettext_noop ("# bytes discarded by TCP (timeout)"),
2074  ret,
2075  GNUNET_NO);
2076  if (0 < ret)
2077  notify_session_monitor (session->plugin,
2078  session,
2080  return 0;
2081  }
2082  /* copy all pending messages that would fit */
2083  ret = 0;
2084  cbuf = buf;
2085  hd = NULL;
2086  tl = NULL;
2087  while (NULL != (pos = session->pending_messages_head))
2088  {
2089  if (ret + pos->message_size > size)
2090  break;
2092  session->pending_messages_tail,
2093  pos);
2094  GNUNET_assert (0 < session->msgs_in_queue);
2095  session->msgs_in_queue--;
2096  GNUNET_assert (pos->message_size <= session->bytes_in_queue);
2097  session->bytes_in_queue -= pos->message_size;
2098  GNUNET_assert(size >= pos->message_size);
2100  "Transmitting message of type %u size %u to peer %s at %s\n",
2101  ntohs (((struct GNUNET_MessageHeader *) pos->msg)->type),
2102  pos->message_size,
2103  GNUNET_i2s (&session->target),
2105  session->address->address,
2106  session->address->address_length));
2107  /* FIXME: this GNUNET_memcpy can be up to 7% of our total runtime */
2108  GNUNET_memcpy (cbuf,
2109  pos->msg,
2110  pos->message_size);
2111  cbuf += pos->message_size;
2112  ret += pos->message_size;
2113  size -= pos->message_size;
2115  tl,
2116  pos);
2117  }
2118  notify_session_monitor (session->plugin,
2119  session,
2121  /* schedule 'continuation' before callbacks so that callbacks that
2122  * cancel everything don't cause us to use a session that no longer
2123  * exists... */
2124  process_pending_messages (session);
2126  pid = session->target;
2127  /* we'll now call callbacks that may cancel the session; hence
2128  * we should not use 'session' after this point */
2129  while (NULL != (pos = hd))
2130  {
2131  GNUNET_CONTAINER_DLL_remove (hd, tl, pos);
2132  if (NULL != pos->transmit_cont)
2133  pos->transmit_cont (pos->transmit_cont_cls,
2134  &pid,
2135  GNUNET_OK,
2136  pos->message_size,
2137  pos->message_size); /* FIXME: include TCP overhead */
2138  GNUNET_free (pos);
2139  }
2140  GNUNET_assert (NULL == hd);
2141  GNUNET_assert (NULL == tl);
2142  GNUNET_STATISTICS_update (plugin->env->stats,
2143  gettext_noop ("# bytes currently in TCP buffers"),
2144  - (int64_t) ret,
2145  GNUNET_NO);
2146  GNUNET_STATISTICS_update (plugin->env->stats,
2147  gettext_noop ("# bytes transmitted via TCP"),
2148  ret,
2149  GNUNET_NO);
2150  return ret;
2151 }
2152 
2153 
2160 static void
2162 {
2163  struct PendingMessage *pm;
2164 
2165  GNUNET_assert (NULL != session->client);
2166  if (NULL != session->transmit_handle)
2167  return;
2168  if (NULL == (pm = session->pending_messages_head))
2169  return;
2170 
2171  session->transmit_handle
2173  pm->message_size,
2175  &do_transmit,
2176  session);
2177 }
2178 
2179 
2207 static ssize_t
2208 tcp_plugin_send (void *cls,
2209  struct GNUNET_ATS_Session *session,
2210  const char *msgbuf,
2211  size_t msgbuf_size,
2212  unsigned int priority,
2213  struct GNUNET_TIME_Relative to,
2215  void *cont_cls)
2216 {
2217  struct Plugin * plugin = cls;
2218  struct PendingMessage *pm;
2219 
2220  /* create new message entry */
2221  pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size);
2222  pm->msg = (const char *) &pm[1];
2223  GNUNET_memcpy (&pm[1], msgbuf, msgbuf_size);
2224  pm->message_size = msgbuf_size;
2226  pm->transmit_cont = cont;
2227  pm->transmit_cont_cls = cont_cls;
2228 
2230  "Asked to transmit %u bytes to `%s', added message to list.\n",
2231  msgbuf_size,
2232  GNUNET_i2s (&session->target));
2233 
2234  if (GNUNET_YES ==
2236  &session->target,
2237  session))
2238  {
2239  GNUNET_assert (NULL != session->client);
2242  GNUNET_STATISTICS_update (plugin->env->stats,
2243  gettext_noop ("# bytes currently in TCP buffers"),
2244  msgbuf_size,
2245  GNUNET_NO);
2246 
2247  /* append pm to pending_messages list */
2249  session->pending_messages_tail,
2250  pm);
2251  notify_session_monitor (session->plugin,
2252  session,
2254  session->msgs_in_queue++;
2255  session->bytes_in_queue += pm->message_size;
2256  process_pending_messages (session);
2257  return msgbuf_size;
2258  }
2259  if (GNUNET_YES ==
2261  &session->target,
2262  session))
2263  {
2265  "This NAT WAIT session for peer `%s' is not yet ready!\n",
2266  GNUNET_i2s (&session->target));
2267  GNUNET_STATISTICS_update (plugin->env->stats,
2268  gettext_noop ("# bytes currently in TCP buffers"), msgbuf_size,
2269  GNUNET_NO);
2270  /* append pm to pending_messages list */
2272  session->pending_messages_tail,
2273  pm);
2274  session->msgs_in_queue++;
2275  session->bytes_in_queue += pm->message_size;
2276  notify_session_monitor (session->plugin,
2277  session,
2279  return msgbuf_size;
2280  }
2282  "Invalid session %p\n",
2283  session);
2284  if (NULL != cont)
2285  cont (cont_cls,
2286  &session->target,
2287  GNUNET_SYSERR,
2288  pm->message_size,
2289  0);
2290  GNUNET_break (0);
2291  GNUNET_free (pm);
2292  return GNUNET_SYSERR; /* session does not exist here */
2293 }
2294 
2295 
2300 {
2305 
2310 
2311 };
2312 
2313 
2322 static int
2324  const struct GNUNET_PeerIdentity *key,
2325  void *value)
2326 {
2327  struct GNUNET_ATS_SessionItCtx *si_ctx = cls;
2328  struct GNUNET_ATS_Session *session = value;
2329 
2330  if (0 !=
2332  session->address))
2333  return GNUNET_YES;
2334  si_ctx->result = session;
2335  return GNUNET_NO;
2336 }
2337 
2338 
2344 static void
2346 {
2347  struct GNUNET_ATS_Session *session = cls;
2348 
2349  session->nat_connection_timeout = NULL;
2351  "NAT WAIT connection to `%4s' at `%s' could not be established, removing session\n",
2352  GNUNET_i2s (&session->target),
2354  session->address->address,
2355  session->address->address_length));
2357  session);
2358 }
2359 
2360 
2370 static void
2372  const struct GNUNET_PeerIdentity *peer,
2373  struct GNUNET_ATS_Session *session)
2374 {
2375  reschedule_session_timeout (session);
2376 }
2377 
2378 
2385 static void
2386 delayed_done (void *cls)
2387 {
2388  struct GNUNET_ATS_Session *session = cls;
2389 
2390  session->receive_delay_task = NULL;
2391  reschedule_session_timeout (session);
2393  GNUNET_OK);
2394 }
2395 
2396 
2407 static void
2409  const struct GNUNET_PeerIdentity *peer,
2410  struct GNUNET_ATS_Session *session,
2411  struct GNUNET_TIME_Relative delay)
2412 {
2413  if (NULL == session->receive_delay_task)
2414  return;
2416  "New inbound delay %s\n",
2418  GNUNET_NO));
2422  &delayed_done,
2423  session);
2424 }
2425 
2426 
2436 static struct GNUNET_ATS_Session *
2438  const struct GNUNET_HELLO_Address *address)
2439 {
2440  struct Plugin *plugin = cls;
2441  struct GNUNET_ATS_Session *session = NULL;
2442  int af;
2443  const void *sb;
2444  size_t sbs;
2445  struct GNUNET_CONNECTION_Handle *sa;
2446  struct sockaddr_in a4;
2447  struct sockaddr_in6 a6;
2448  const struct IPv4TcpAddress *t4;
2449  const struct IPv6TcpAddress *t6;
2450  unsigned int options;
2451  enum GNUNET_NetworkType net_type;
2452  unsigned int is_natd = GNUNET_NO;
2453  size_t addrlen;
2454 #ifdef TCP_STEALTH
2455  struct GNUNET_NETWORK_Handle *s;
2456 #endif
2457 
2458  addrlen = address->address_length;
2460  "Trying to get session for `%s' address of peer `%s'\n",
2462  address->address,
2463  address->address_length),
2464  GNUNET_i2s (&address->peer));
2465 
2466  if (GNUNET_HELLO_address_check_option (address,
2468  {
2469  GNUNET_break (0);
2470  return NULL;
2471  }
2472 
2473  /* look for existing session */
2474  if (GNUNET_YES ==
2476  &address->peer))
2477  {
2478  struct GNUNET_ATS_SessionItCtx si_ctx;
2479 
2480  si_ctx.address = address;
2481  si_ctx.result = NULL;
2483  &address->peer,
2485  &si_ctx);
2486  if (NULL != si_ctx.result)
2487  {
2488  session = si_ctx.result;
2490  "Found existing session for `%s' address `%s'\n",
2491  GNUNET_i2s (&address->peer),
2493  address->address,
2494  address->address_length));
2495  return session;
2496  }
2497  /* This is a bit of a hack, limiting TCP to never allow more than
2498  one TCP connection to any given peer at the same time.
2499  Without this, peers sometimes disagree about which of the TCP
2500  connections they should use, causing one side to believe that
2501  they transmit successfully, while the other receives nothing. */
2502  return NULL; /* Refuse to have more than one TCP connection per
2503  peer pair at the same time. */
2504  }
2505 
2506  if (addrlen == sizeof(struct IPv6TcpAddress))
2507  {
2508  GNUNET_assert (NULL != address->address); /* make static analysis happy */
2509  t6 = address->address;
2510  options = t6->options;
2511  af = AF_INET6;
2512  memset (&a6, 0, sizeof(a6));
2513 #if HAVE_SOCKADDR_IN_SIN_LEN
2514  a6.sin6_len = sizeof (a6);
2515 #endif
2516  a6.sin6_family = AF_INET6;
2517  a6.sin6_port = t6->t6_port;
2518  if (t6->t6_port == 0)
2519  is_natd = GNUNET_YES;
2520  GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
2521  sb = &a6;
2522  sbs = sizeof(a6);
2523  }
2524  else if (addrlen == sizeof(struct IPv4TcpAddress))
2525  {
2526  GNUNET_assert(NULL != address->address); /* make static analysis happy */
2527  t4 = address->address;
2528  options = t4->options;
2529  af = AF_INET;
2530  memset (&a4, 0, sizeof(a4));
2531 #if HAVE_SOCKADDR_IN_SIN_LEN
2532  a4.sin_len = sizeof (a4);
2533 #endif
2534  a4.sin_family = AF_INET;
2535  a4.sin_port = t4->t4_port;
2536  if (t4->t4_port == 0)
2537  is_natd = GNUNET_YES;
2538  a4.sin_addr.s_addr = t4->ipv4_addr;
2539  sb = &a4;
2540  sbs = sizeof(a4);
2541  }
2542  else
2543  {
2544  GNUNET_STATISTICS_update (plugin->env->stats,
2545  gettext_noop ("# requests to create session with invalid address"),
2546  1,
2547  GNUNET_NO);
2548  return NULL;
2549  }
2550 
2551  net_type = plugin->env->get_address_type (plugin->env->cls,
2552  sb,
2553  sbs);
2554  GNUNET_break (net_type != GNUNET_NT_UNSPECIFIED);
2555 
2556  if ( (is_natd == GNUNET_YES) &&
2557  (addrlen == sizeof(struct IPv6TcpAddress)) )
2558  {
2559  /* NAT client only works with IPv4 addresses */
2560  return NULL;
2561  }
2562 
2563  if (plugin->cur_connections >= plugin->max_connections)
2564  {
2565  /* saturated */
2566  return NULL;
2567  }
2568 
2569  if ( (is_natd == GNUNET_YES) &&
2570  (GNUNET_YES ==
2572  &address->peer)))
2573  {
2574  /* Only do one NAT punch attempt per peer identity */
2575  return NULL;
2576  }
2577 
2578  if ( (is_natd == GNUNET_YES) &&
2579  (NULL != plugin->nat) &&
2580  (GNUNET_NO ==
2582  &address->peer)))
2583  {
2584  struct sockaddr_in local_sa;
2585 
2587  "Found valid IPv4 NAT address (creating session)!\n");
2588  session = create_session (plugin,
2589  address,
2590  net_type,
2591  NULL,
2592  GNUNET_YES);
2595  session);
2598  &session->target,
2599  session,
2601 
2603  "Created NAT WAIT connection to `%s' at `%s'\n",
2604  GNUNET_i2s (&session->target),
2605  GNUNET_a2s (sb, sbs));
2606  memset (&local_sa,
2607  0,
2608  sizeof (local_sa));
2609  local_sa.sin_family = AF_INET;
2610  local_sa.sin_port = htons (plugin->open_port);
2611  /* We leave sin_address at 0, let the kernel figure it out,
2612  even if our bind() is more specific. (May want to reconsider
2613  later.) */
2614  if (GNUNET_OK ==
2616  &local_sa,
2617  &a4))
2618  return session;
2620  "Running NAT client for `%s' at `%s' failed\n",
2621  GNUNET_i2s (&session->target),
2622  GNUNET_a2s (sb, sbs));
2624  session);
2625  return NULL;
2626  }
2627 
2628  /* create new outbound session */
2629  if (0 != (options & TCP_OPTIONS_TCP_STEALTH))
2630  {
2631 #ifdef TCP_STEALTH
2632  s = GNUNET_NETWORK_socket_create (af, SOCK_STREAM, 0);
2633  if (NULL == s)
2634  {
2636  "socket");
2637  sa = NULL;
2638  }
2639  else
2640  {
2641  if ( (GNUNET_OK !=
2643  IPPROTO_TCP,
2644  TCP_STEALTH,
2645  &session->target,
2646  sizeof (struct GNUNET_PeerIdentity))) ||
2647  (GNUNET_OK !=
2649  IPPROTO_TCP,
2650  TCP_STEALTH_INTEGRITY,
2651  &plugin->my_welcome,
2652  sizeof (struct WelcomeMessage))) )
2653  {
2654  /* TCP STEALTH not supported by kernel */
2657  sa = NULL;
2658  }
2659  else
2660  {
2661  sa = GNUNET_CONNECTION_connect_socket (s, sb, sbs);
2662  }
2663  }
2664 #else
2665  sa = NULL;
2666 #endif
2667  }
2668  else
2669  {
2670  sa = GNUNET_CONNECTION_create_from_sockaddr (af, sb, sbs);
2671  }
2672  if (NULL == sa)
2673  {
2675  "Failed to create connection to `%s' at `%s'\n",
2676  GNUNET_i2s (&address->peer),
2677  GNUNET_a2s (sb, sbs));
2678  return NULL;
2679  }
2681  "Asked to transmit to `%s', creating fresh session using address `%s'.\n",
2682  GNUNET_i2s (&address->peer),
2683  GNUNET_a2s (sb, sbs));
2684 
2685  session = create_session (plugin,
2686  address,
2687  net_type,
2689  sa),
2690  GNUNET_NO);
2692  &session->target,
2693  session,
2695  /* Send TCP Welcome */
2696  process_pending_messages (session);
2697 
2698  return session;
2699 }
2700 
2701 
2712 static int
2714  const struct GNUNET_PeerIdentity *key,
2715  void *value)
2716 {
2717  struct Plugin *plugin = cls;
2718  struct GNUNET_ATS_Session *session = value;
2719 
2720  GNUNET_STATISTICS_update (session->plugin->env->stats,
2721  gettext_noop ("# transport-service disconnect requests for TCP"),
2722  1,
2723  GNUNET_NO);
2725  session);
2726  return GNUNET_YES;
2727 }
2728 
2729 
2746 static void
2748  const struct GNUNET_PeerIdentity *target)
2749 {
2750  struct Plugin *plugin = cls;
2751 
2753  "Disconnecting peer `%s'\n",
2754  GNUNET_i2s (target));
2756  target,
2758  plugin);
2760  target,
2762  plugin);
2763 }
2764 
2765 
2776 static void
2777 append_port (void *cls,
2778  const char *hostname)
2779 {
2780  struct PrettyPrinterContext *ppc = cls;
2781  struct Plugin *plugin = ppc->plugin;
2782  char *ret;
2783 
2785  "append_port called with hostname `%s'\n",
2786  hostname);
2787  if (NULL == hostname)
2788  {
2789  /* Final call, done */
2790  ppc->resolver_handle = NULL;
2792  plugin->ppc_dll_tail,
2793  ppc);
2794  ppc->asc (ppc->asc_cls,
2795  NULL,
2796  GNUNET_OK);
2797  GNUNET_free (ppc);
2798  return;
2799  }
2800  if (GNUNET_YES == ppc->ipv6)
2801  GNUNET_asprintf (&ret,
2802  "%s.%u.[%s]:%d",
2803  PLUGIN_NAME,
2804  ppc->options,
2805  hostname,
2806  ppc->port);
2807  else
2808  GNUNET_asprintf (&ret,
2809  "%s.%u.%s:%d",
2810  PLUGIN_NAME,
2811  ppc->options,
2812  hostname,
2813  ppc->port);
2814  ppc->asc (ppc->asc_cls,
2815  ret,
2816  GNUNET_OK);
2817  GNUNET_free (ret);
2818 }
2819 
2820 
2834 static void
2836  const char *type,
2837  const void *addr,
2838  size_t addrlen,
2839  int numeric,
2842  void *asc_cls)
2843 {
2844  struct Plugin *plugin = cls;
2845  struct PrettyPrinterContext *ppc;
2846  const void *sb;
2847  size_t sbs;
2848  struct sockaddr_in a4;
2849  struct sockaddr_in6 a6;
2850  const struct IPv4TcpAddress *t4;
2851  const struct IPv6TcpAddress *t6;
2852  uint16_t port;
2853  uint32_t options;
2854 
2855  if (sizeof(struct IPv6TcpAddress) == addrlen)
2856  {
2857  t6 = addr;
2858  memset (&a6, 0, sizeof(a6));
2859  a6.sin6_family = AF_INET6;
2860  a6.sin6_port = t6->t6_port;
2861  GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
2862  port = ntohs (t6->t6_port);
2863  options = ntohl (t6->options);
2864  sb = &a6;
2865  sbs = sizeof(a6);
2866  }
2867  else if (sizeof(struct IPv4TcpAddress) == addrlen)
2868  {
2869  t4 = addr;
2870  memset (&a4, 0, sizeof(a4));
2871  a4.sin_family = AF_INET;
2872  a4.sin_port = t4->t4_port;
2873  a4.sin_addr.s_addr = t4->ipv4_addr;
2874  port = ntohs (t4->t4_port);
2875  options = ntohl (t4->options);
2876  sb = &a4;
2877  sbs = sizeof(a4);
2878  }
2879  else
2880  {
2881  /* invalid address */
2883  _("Unexpected address length: %u bytes\n"),
2884  (unsigned int) addrlen);
2885  asc (asc_cls, NULL, GNUNET_SYSERR);
2886  asc (asc_cls, NULL, GNUNET_OK);
2887  return;
2888  }
2889  ppc = GNUNET_new (struct PrettyPrinterContext);
2890  ppc->plugin = plugin;
2891  if (addrlen == sizeof(struct IPv6TcpAddress))
2892  ppc->ipv6 = GNUNET_YES;
2893  else
2894  ppc->ipv6 = GNUNET_NO;
2895  ppc->asc = asc;
2896  ppc->asc_cls = asc_cls;
2897  ppc->port = port;
2898  ppc->options = options;
2900  "Starting DNS reverse lookup\n");
2902  sbs,
2903  ! numeric,
2904  timeout,
2905  &append_port,
2906  ppc);
2907  if (NULL == ppc->resolver_handle)
2908  {
2909  GNUNET_break (0);
2910  GNUNET_free (ppc);
2911  return;
2912  }
2914  plugin->ppc_dll_tail,
2915  ppc);
2916 }
2917 
2918 
2934 static int
2936  const void *addr,
2937  size_t addrlen)
2938 {
2939  struct Plugin *plugin = cls;
2940  const struct IPv4TcpAddress *v4;
2941  const struct IPv6TcpAddress *v6;
2942 
2943  if ( (addrlen != sizeof(struct IPv4TcpAddress)) &&
2944  (addrlen != sizeof(struct IPv6TcpAddress)) )
2945  {
2946  GNUNET_break_op (0);
2947  return GNUNET_SYSERR;
2948  }
2949 
2950  if (addrlen == sizeof(struct IPv4TcpAddress))
2951  {
2952  struct sockaddr_in s4;
2953 
2954  v4 = (const struct IPv4TcpAddress *) addr;
2955  if (0 != memcmp (&v4->options,
2956  &plugin->myoptions,
2957  sizeof(uint32_t)))
2958  {
2959  GNUNET_break (0);
2960  return GNUNET_SYSERR;
2961  }
2962  memset (&s4, 0, sizeof (s4));
2963  s4.sin_family = AF_INET;
2964 #if HAVE_SOCKADDR_IN_SIN_LEN
2965  s4.sin_len = sizeof (s4);
2966 #endif
2967  s4.sin_port = v4->t4_port;
2968  s4.sin_addr.s_addr = v4->ipv4_addr;
2969 
2970  if (GNUNET_OK !=
2971  GNUNET_NAT_test_address (plugin->nat,
2972  &s4,
2973  sizeof (struct sockaddr_in)))
2974  return GNUNET_SYSERR;
2975  }
2976  else
2977  {
2978  struct sockaddr_in6 s6;
2979 
2980  v6 = (const struct IPv6TcpAddress *) addr;
2981  if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
2982  {
2983  GNUNET_break_op (0);
2984  return GNUNET_SYSERR;
2985  }
2986  if (0 != memcmp (&v6->options,
2987  &plugin->myoptions,
2988  sizeof (uint32_t)))
2989  {
2990  GNUNET_break (0);
2991  return GNUNET_SYSERR;
2992  }
2993  memset (&s6, 0, sizeof (s6));
2994  s6.sin6_family = AF_INET6;
2995 #if HAVE_SOCKADDR_IN_SIN_LEN
2996  s6.sin6_len = sizeof (s6);
2997 #endif
2998  s6.sin6_port = v6->t6_port;
2999  s6.sin6_addr = v6->ipv6_addr;
3000 
3001  if (GNUNET_OK !=
3002  GNUNET_NAT_test_address (plugin->nat,
3003  &s6,
3004  sizeof(struct sockaddr_in6)))
3005  return GNUNET_SYSERR;
3006  }
3007  return GNUNET_OK;
3008 }
3009 
3010 
3020 static void
3022  struct GNUNET_SERVER_Client *client,
3023  const struct GNUNET_MessageHeader *message)
3024 {
3025  struct Plugin *plugin = cls;
3026  struct GNUNET_ATS_Session *session;
3027  const struct TCP_NAT_ProbeMessage *tcp_nat_probe;
3028  size_t alen;
3029  void *vaddr;
3030  struct IPv4TcpAddress *t4;
3031  struct IPv6TcpAddress *t6;
3032  const struct sockaddr_in *s4;
3033  const struct sockaddr_in6 *s6;
3034 
3036  "Received NAT probe\n");
3037  /* We have received a TCP NAT probe, meaning we (hopefully) initiated
3038  * a connection to this peer by running gnunet-nat-client. This peer
3039  * received the punch message and now wants us to use the new connection
3040  * as the default for that peer. Do so and then send a WELCOME message
3041  * so we can really be connected!
3042  */
3043  if (ntohs (message->size) != sizeof(struct TCP_NAT_ProbeMessage))
3044  {
3045  GNUNET_break_op(0);
3047  GNUNET_SYSERR);
3048  return;
3049  }
3050 
3051  tcp_nat_probe = (const struct TCP_NAT_ProbeMessage *) message;
3052  if (0 == memcmp (&tcp_nat_probe->clientIdentity, plugin->env->my_identity,
3053  sizeof(struct GNUNET_PeerIdentity)))
3054  {
3055  /* refuse connections from ourselves */
3057  GNUNET_SYSERR);
3058  return;
3059  }
3060 
3062  &tcp_nat_probe->clientIdentity);
3063  if (NULL == session)
3064  {
3066  "Did NOT find session for NAT probe!\n");
3068  GNUNET_OK);
3069  return;
3070  }
3072  "Found session for NAT probe!\n");
3073 
3074  if (NULL != session->nat_connection_timeout)
3075  {
3077  session->nat_connection_timeout = NULL;
3078  }
3079 
3080  if (GNUNET_OK !=
3082  &vaddr,
3083  &alen))
3084  {
3085  GNUNET_break(0);
3087  GNUNET_SYSERR);
3089  session);
3090  return;
3091  }
3094  &tcp_nat_probe->clientIdentity,
3095  session));
3097  session);
3099  &session->target,
3100  session,
3104  "Found address `%s' for incoming connection\n",
3105  GNUNET_a2s (vaddr, alen));
3106  switch (((const struct sockaddr *) vaddr)->sa_family)
3107  {
3108  case AF_INET:
3109  s4 = vaddr;
3110  t4 = GNUNET_new (struct IPv4TcpAddress);
3111  t4->options = htonl (TCP_OPTIONS_NONE);
3112  t4->t4_port = s4->sin_port;
3113  t4->ipv4_addr = s4->sin_addr.s_addr;
3114  session->address = GNUNET_HELLO_address_allocate (&tcp_nat_probe->clientIdentity,
3115  PLUGIN_NAME,
3116  &t4,
3117  sizeof(struct IPv4TcpAddress),
3119  break;
3120  case AF_INET6:
3121  s6 = vaddr;
3122  t6 = GNUNET_new (struct IPv6TcpAddress);
3123  t6->options = htonl (TCP_OPTIONS_NONE);
3124  t6->t6_port = s6->sin6_port;
3125  GNUNET_memcpy (&t6->ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
3126  session->address = GNUNET_HELLO_address_allocate (&tcp_nat_probe->clientIdentity,
3127  PLUGIN_NAME,
3128  &t6,
3129  sizeof(struct IPv6TcpAddress),
3131  break;
3132  default:
3133  GNUNET_break_op(0);
3135  "Bad address for incoming connection!\n");
3136  GNUNET_free(vaddr);
3138  GNUNET_SYSERR);
3140  session);
3141  return;
3142  }
3143  GNUNET_free (vaddr);
3144  GNUNET_break (NULL == session->client);
3145  session->client = client;
3146  GNUNET_STATISTICS_update (plugin->env->stats,
3147  gettext_noop ("# TCP sessions active"),
3148  1,
3149  GNUNET_NO);
3150  process_pending_messages (session);
3152  GNUNET_OK);
3153 }
3154 
3155 
3164 static void
3166  struct GNUNET_SERVER_Client *client,
3167  const struct GNUNET_MessageHeader *message)
3168 {
3169  struct Plugin *plugin = cls;
3170  const struct WelcomeMessage *wm = (const struct WelcomeMessage *) message;
3171  struct GNUNET_HELLO_Address *address;
3172  struct GNUNET_ATS_Session *session;
3173  size_t alen;
3174  void *vaddr;
3175  struct IPv4TcpAddress t4;
3176  struct IPv6TcpAddress t6;
3177  const struct sockaddr_in *s4;
3178  const struct sockaddr_in6 *s6;
3179 
3180  if (0 == memcmp (&wm->clientIdentity,
3181  plugin->env->my_identity,
3182  sizeof(struct GNUNET_PeerIdentity)))
3183  {
3184  /* refuse connections from ourselves */
3185  if (GNUNET_OK ==
3187  &vaddr,
3188  &alen))
3189  {
3191  "Received WELCOME message from my own identity `%s' on address `%s'\n",
3192  GNUNET_i2s (&wm->clientIdentity),
3193  GNUNET_a2s (vaddr, alen));
3194  GNUNET_free (vaddr);
3195  }
3197  GNUNET_SYSERR);
3198  return;
3199  }
3200 
3201  if (GNUNET_OK ==
3203  &vaddr,
3204  &alen))
3205  {
3207  "Received WELCOME message from `%s' on address `%s'\n",
3208  GNUNET_i2s (&wm->clientIdentity),
3209  GNUNET_a2s (vaddr, alen));
3210  GNUNET_free (vaddr);
3211  }
3212  GNUNET_STATISTICS_update (plugin->env->stats,
3213  gettext_noop ("# TCP WELCOME messages received"),
3214  1,
3215  GNUNET_NO);
3216  session = lookup_session_by_client (plugin,
3217  client);
3218  if (NULL != session)
3219  {
3220  if (GNUNET_OK ==
3222  &vaddr,
3223  &alen))
3224  {
3226  "Found existing session %p for peer `%s'\n",
3227  session,
3228  GNUNET_a2s (vaddr, alen));
3229  GNUNET_free (vaddr);
3230  }
3231  }
3232  else
3233  {
3234  if (GNUNET_OK ==
3235  GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
3236  {
3237  if (alen == sizeof(struct sockaddr_in))
3238  {
3239  s4 = vaddr;
3240  memset (&t4, '\0', sizeof (t4));
3241  t4.options = htonl (TCP_OPTIONS_NONE);
3242  t4.t4_port = s4->sin_port;
3243  t4.ipv4_addr = s4->sin_addr.s_addr;
3245  PLUGIN_NAME,
3246  &t4,
3247  sizeof(t4),
3249  }
3250  else if (alen == sizeof(struct sockaddr_in6))
3251  {
3252  s6 = vaddr;
3253  memset (&t6, '\0', sizeof (t6));
3254  t6.options = htonl (TCP_OPTIONS_NONE);
3255  t6.t6_port = s6->sin6_port;
3256  GNUNET_memcpy (&t6.ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
3258  PLUGIN_NAME,
3259  &t6,
3260  sizeof (t6),
3262  }
3263  else
3264  {
3265  GNUNET_break (0);
3266  GNUNET_free_non_null (vaddr);
3268  GNUNET_SYSERR);
3269  return;
3270  }
3271  session = create_session (plugin,
3272  address,
3273  plugin->env->get_address_type (plugin->env->cls,
3274  vaddr,
3275  alen),
3276  client,
3277  GNUNET_NO);
3279  GNUNET_HELLO_address_free (address);
3281  "Creating new%s session %p for peer `%s' client %p\n",
3284  ? " inbound" : "",
3285  session,
3287  session->address->address,
3288  session->address->address_length),
3289  client);
3290  GNUNET_free (vaddr);
3292  &session->target,
3293  session,
3295  /* Notify transport and ATS about new session */
3296  plugin->env->session_start (plugin->env->cls,
3297  session->address,
3298  session,
3299  session->scope);
3300  }
3301  else
3302  {
3304  "Did not obtain TCP socket address for incoming connection\n");
3305  GNUNET_break(0);
3307  GNUNET_SYSERR);
3308  return;
3309  }
3310  }
3311 
3312  if (GNUNET_YES != session->expecting_welcome)
3313  {
3314  GNUNET_break_op (0);
3316  GNUNET_SYSERR);
3317  return;
3318  }
3320  session->expecting_welcome = GNUNET_NO;
3321 
3322  process_pending_messages (session);
3326  GNUNET_OK);
3327 }
3328 
3329 
3338 static void
3339 handle_tcp_data (void *cls,
3340  struct GNUNET_SERVER_Client *client,
3341  const struct GNUNET_MessageHeader *message)
3342 {
3343  struct Plugin *plugin = cls;
3344  struct GNUNET_ATS_Session *session;
3345  struct GNUNET_TIME_Relative delay;
3346  uint16_t type;
3347 
3348  type = ntohs (message->type);
3351  {
3352  /* We don't want to propagate WELCOME and NAT Probe messages up! */
3354  GNUNET_OK);
3355  return;
3356  }
3357  session = lookup_session_by_client (plugin, client);
3358  if (NULL == session)
3359  {
3360  /* No inbound session found */
3361  void *vaddr = NULL;
3362  size_t alen;
3363 
3366  &vaddr,
3367  &alen));
3369  "Received unexpected %u bytes of type %u from `%s'\n",
3370  (unsigned int) ntohs (message->size),
3371  (unsigned int) ntohs (message->type),
3372  GNUNET_a2s (vaddr,
3373  alen));
3374  GNUNET_break_op(0);
3376  GNUNET_SYSERR);
3377  GNUNET_free_non_null (vaddr);
3378  return;
3379  }
3380  if (GNUNET_YES == session->expecting_welcome)
3381  {
3382  /* Session is expecting WELCOME message */
3383  void *vaddr = NULL;
3384  size_t alen;
3385 
3387  &vaddr,
3388  &alen);
3390  "Received unexpected %u bytes of type %u from `%s'\n",
3391  (unsigned int) ntohs (message->size),
3392  (unsigned int) ntohs (message->type),
3393  GNUNET_a2s (vaddr, alen));
3394  GNUNET_break_op(0);
3396  GNUNET_SYSERR);
3397  GNUNET_free_non_null (vaddr);
3398  return;
3399  }
3400 
3402  {
3403  void *vaddr = NULL;
3404  size_t alen;
3405 
3407  &vaddr,
3408  &alen);
3410  "Passing %u bytes of type %u from `%s' at %s to transport service.\n",
3411  (unsigned int) ntohs (message->size),
3412  (unsigned int) ntohs (message->type),
3413  GNUNET_i2s (&session->target),
3414  GNUNET_a2s (vaddr, alen));
3415  GNUNET_free_non_null (vaddr);
3416  }
3417 
3418  GNUNET_STATISTICS_update (plugin->env->stats,
3419  gettext_noop ("# bytes received via TCP"),
3420  ntohs (message->size),
3421  GNUNET_NO);
3422 
3424  &session->target,
3425  session));
3426  delay = plugin->env->receive (plugin->env->cls,
3427  session->address,
3428  session,
3429  message);
3430  reschedule_session_timeout (session);
3431  if (0 == delay.rel_value_us)
3432  {
3434  GNUNET_OK);
3435  }
3436  else
3437  {
3439  "Throttling receiving from `%s' for %s\n",
3440  GNUNET_i2s (&session->target),
3442  GNUNET_YES));
3444  GNUNET_assert (NULL == session->receive_delay_task);
3446  &delayed_done,
3447  session);
3448  }
3449 }
3450 
3451 
3460 static void
3461 connect_notify (void *cls,
3462  struct GNUNET_SERVER_Client *client)
3463 {
3464  struct Plugin *plugin = cls;
3465 
3466  if (NULL == client)
3467  return;
3468  plugin->cur_connections++;
3469  GNUNET_STATISTICS_set (plugin->env->stats,
3470  gettext_noop ("# TCP server connections active"),
3471  plugin->cur_connections,
3472  GNUNET_NO);
3473  GNUNET_STATISTICS_update (plugin->env->stats,
3474  gettext_noop ("# TCP server connect events"),
3475  1,
3476  GNUNET_NO);
3477  if (plugin->cur_connections != plugin->max_connections)
3478  return;
3480  _("TCP connection limit reached, suspending server\n"));
3481  GNUNET_STATISTICS_update (plugin->env->stats,
3482  gettext_noop ("# TCP service suspended"),
3483  1,
3484  GNUNET_NO);
3485  GNUNET_SERVER_suspend (plugin->server); /* Maximum number of connections rechead */
3486 }
3487 
3488 
3497 static void
3499  struct GNUNET_SERVER_Client *client)
3500 {
3501  struct Plugin *plugin = cls;
3502  struct GNUNET_ATS_Session *session;
3503 
3504  if (NULL == client)
3505  return;
3506  GNUNET_assert (plugin->cur_connections >= 1);
3507  plugin->cur_connections--;
3508  session = lookup_session_by_client (plugin,
3509  client);
3510  if (NULL == session)
3511  return; /* unknown, nothing to do */
3513  "Destroying session of `%s' with %s due to network-level disconnect.\n",
3514  GNUNET_i2s (&session->target),
3516  session->address->address,
3517  session->address->address_length));
3518 
3519  if (plugin->cur_connections == plugin->max_connections)
3520  {
3521  GNUNET_STATISTICS_update (session->plugin->env->stats,
3522  gettext_noop ("# TCP service resumed"),
3523  1,
3524  GNUNET_NO);
3525  GNUNET_SERVER_resume (plugin->server); /* Resume server */
3526  }
3527  GNUNET_STATISTICS_set (plugin->env->stats,
3528  gettext_noop ("# TCP server connections active"),
3529  plugin->cur_connections,
3530  GNUNET_NO);
3531  GNUNET_STATISTICS_update (session->plugin->env->stats,
3532  gettext_noop ("# network-level TCP disconnect events"),
3533  1,
3534  GNUNET_NO);
3536  session);
3537 }
3538 
3539 
3548 static size_t
3550  size_t size,
3551  void *buf)
3552 {
3553  struct TCPProbeContext *tcp_probe_ctx = cls;
3554  struct Plugin *plugin = tcp_probe_ctx->plugin;
3555  size_t ret;
3556 
3557  tcp_probe_ctx->transmit_handle = NULL;
3559  plugin->probe_tail,
3560  tcp_probe_ctx);
3561  if (NULL == buf)
3562  {
3563  GNUNET_CONNECTION_destroy (tcp_probe_ctx->sock);
3564  GNUNET_free(tcp_probe_ctx);
3565  return 0;
3566  }
3567  GNUNET_assert(size >= sizeof(tcp_probe_ctx->message));
3568  GNUNET_memcpy (buf,
3569  &tcp_probe_ctx->message,
3570  sizeof(tcp_probe_ctx->message));
3571  GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server,
3572  tcp_probe_ctx->sock);
3573  ret = sizeof(tcp_probe_ctx->message);
3574  GNUNET_free (tcp_probe_ctx);
3575  return ret;
3576 }
3577 
3578 
3588 static void
3590  const struct sockaddr *addr,
3591  socklen_t addrlen)
3592 {
3593  struct Plugin *plugin = cls;
3595  struct TCPProbeContext *tcp_probe_ctx;
3596 
3602  addr,
3603  addrlen);
3604  if (NULL == sock)
3605  {
3606  /* failed for some odd reason (out of sockets?); ignore attempt */
3607  return;
3608  }
3609 
3610  tcp_probe_ctx = GNUNET_new (struct TCPProbeContext);
3611  tcp_probe_ctx->message.header.size
3612  = htons (sizeof (struct TCP_NAT_ProbeMessage));
3613  tcp_probe_ctx->message.header.type
3615  tcp_probe_ctx->message.clientIdentity
3616  = *plugin->env->my_identity;
3617  tcp_probe_ctx->plugin = plugin;
3618  tcp_probe_ctx->sock = sock;
3620  plugin->probe_tail,
3621  tcp_probe_ctx);
3622  tcp_probe_ctx->transmit_handle
3624  ntohs (tcp_probe_ctx->message.header.size),
3627  tcp_probe_ctx);
3628 }
3629 
3630 
3638 static enum GNUNET_NetworkType
3640  struct GNUNET_ATS_Session *session)
3641 {
3642  return session->scope;
3643 }
3644 
3645 
3653 static enum GNUNET_NetworkType
3655  const struct GNUNET_HELLO_Address *address)
3656 {
3657  struct Plugin *plugin = cls;
3658  size_t addrlen;
3659  struct sockaddr_in a4;
3660  struct sockaddr_in6 a6;
3661  const struct IPv4TcpAddress *t4;
3662  const struct IPv6TcpAddress *t6;
3663  const void *sb;
3664  size_t sbs;
3665 
3666  addrlen = address->address_length;
3667  if (addrlen == sizeof(struct IPv6TcpAddress))
3668  {
3669  GNUNET_assert (NULL != address->address); /* make static analysis happy */
3670  t6 = address->address;
3671  memset (&a6, 0, sizeof(a6));
3672 #if HAVE_SOCKADDR_IN_SIN_LEN
3673  a6.sin6_len = sizeof (a6);
3674 #endif
3675  a6.sin6_family = AF_INET6;
3676  a6.sin6_port = t6->t6_port;
3677  GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
3678  sb = &a6;
3679  sbs = sizeof(a6);
3680  }
3681  else if (addrlen == sizeof(struct IPv4TcpAddress))
3682  {
3683  GNUNET_assert (NULL != address->address); /* make static analysis happy */
3684  t4 = address->address;
3685  memset (&a4, 0, sizeof(a4));
3686 #if HAVE_SOCKADDR_IN_SIN_LEN
3687  a4.sin_len = sizeof (a4);
3688 #endif
3689  a4.sin_family = AF_INET;
3690  a4.sin_port = t4->t4_port;
3691  a4.sin_addr.s_addr = t4->ipv4_addr;
3692  sb = &a4;
3693  sbs = sizeof(a4);
3694  }
3695  else
3696  {
3697  GNUNET_break (0);
3698  return GNUNET_NT_UNSPECIFIED;
3699  }
3700  return plugin->env->get_address_type (plugin->env->cls,
3701  sb,
3702  sbs);
3703 }
3704 
3705 
3715 static int
3717  const struct GNUNET_PeerIdentity *peer,
3718  void *value)
3719 {
3720  struct Plugin *plugin = cls;
3721  struct GNUNET_ATS_Session *session = value;
3722 
3723  notify_session_monitor (plugin,
3724  session,
3726  /* FIXME: cannot tell if this is up or not from current
3727  session state... */
3728  notify_session_monitor (plugin,
3729  session,
3731  return GNUNET_OK;
3732 }
3733 
3734 
3747 static void
3750  void *sic_cls)
3751 {
3752  struct Plugin *plugin = cls;
3753 
3754  plugin->sic = sic;
3755  plugin->sic_cls = sic_cls;
3756  if (NULL != sic)
3757  {
3760  plugin);
3761  /* signal end of first iteration */
3762  sic (sic_cls, NULL, NULL);
3763  }
3764 }
3765 
3766 
3773 void *
3775 {
3776  static const struct GNUNET_SERVER_MessageHandler my_handlers[] = {
3777  { &handle_tcp_welcome, NULL,
3779  sizeof(struct WelcomeMessage) },
3780  { &handle_tcp_nat_probe, NULL,
3782  sizeof(struct TCP_NAT_ProbeMessage) },
3783  { &handle_tcp_data, NULL,
3785  { NULL, NULL, 0, 0 }
3786  };
3789  struct Plugin *plugin;
3791  unsigned long long aport;
3792  unsigned long long bport;
3793  unsigned long long max_connections;
3794  unsigned int i;
3795  struct GNUNET_TIME_Relative idle_timeout;
3796 #ifdef TCP_STEALTH
3797  struct GNUNET_NETWORK_Handle *const*lsocks;
3798 #endif
3799  int ret;
3800  int ret_s;
3801  struct sockaddr **addrs;
3802  socklen_t *addrlens;
3803 
3804  if (NULL == env->receive)
3805  {
3806  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
3807  initialze the plugin or the API */
3809  api->cls = NULL;
3813  return api;
3814  }
3815 
3816  GNUNET_assert (NULL != env->cfg);
3817  if (GNUNET_OK !=
3819  "transport-tcp",
3820  "MAX_CONNECTIONS",
3821  &max_connections))
3822  max_connections = 128;
3823 
3824  aport = 0;
3825  if ((GNUNET_OK !=
3826  GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp",
3827  "PORT", &bport)) ||
3828  (bport > 65535) ||
3829  ((GNUNET_OK ==
3830  GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp",
3831  "ADVERTISED-PORT", &aport)) &&
3832  (aport > 65535) ))
3833  {
3835  _("Require valid port number for service `%s' in configuration!\n"),
3836  "transport-tcp");
3837  return NULL ;
3838  }
3839  if (0 == aport)
3840  aport = bport;
3841  if (0 == bport)
3842  aport = 0;
3843  if (0 != bport)
3844  {
3845  service = LEGACY_SERVICE_start ("transport-tcp",
3846  env->cfg,
3848  if (NULL == service)
3849  {
3851  _("Failed to start service.\n"));
3852  return NULL;
3853  }
3854  }
3855  else
3856  service = NULL;
3857 
3858  api = NULL;
3859  plugin = GNUNET_new (struct Plugin);
3860  plugin->sessionmap = GNUNET_CONTAINER_multipeermap_create (max_connections,
3861  GNUNET_YES);
3862  plugin->max_connections = max_connections;
3863  plugin->open_port = bport;
3864  plugin->adv_port = aport;
3865  plugin->env = env;
3866  plugin->my_welcome.header.size = htons (sizeof(struct WelcomeMessage));
3867  plugin->my_welcome.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME);
3868  plugin->my_welcome.clientIdentity = *plugin->env->my_identity;
3869 
3870  if ( (NULL != service) &&
3871  (GNUNET_YES ==
3873  "transport-tcp",
3874  "TCP_STEALTH")) )
3875  {
3876 #ifdef TCP_STEALTH
3878  lsocks = LEGACY_SERVICE_get_listen_sockets (service);
3879  if (NULL != lsocks)
3880  {
3881  uint32_t len = sizeof (struct WelcomeMessage);
3882 
3883  for (i=0;NULL!=lsocks[i];i++)
3884  {
3885  if ( (GNUNET_OK !=
3887  IPPROTO_TCP,
3888  TCP_STEALTH,
3889  env->my_identity,
3890  sizeof (struct GNUNET_PeerIdentity))) ||
3891  (GNUNET_OK !=
3893  IPPROTO_TCP,
3894  TCP_STEALTH_INTEGRITY_LEN,
3895  &len,
3896  sizeof (len))) )
3897  {
3898  /* TCP STEALTH not supported by kernel */
3899  GNUNET_assert (0 == i);
3901  _("TCP_STEALTH not supported on this platform.\n"));
3902  goto die;
3903  }
3904  }
3905  }
3906 #else
3908  _("TCP_STEALTH not supported on this platform.\n"));
3909  goto die;
3910 #endif
3911  }
3912 
3913  if ( (NULL != service) &&
3914  (GNUNET_SYSERR !=
3915  (ret_s =
3916  get_server_addresses ("transport-tcp",
3917  env->cfg,
3918  &addrs,
3919  &addrlens))))
3920  {
3921  for (ret = ret_s-1; ret >= 0; ret--)
3923  "Binding to address `%s'\n",
3924  GNUNET_a2s (addrs[ret], addrlens[ret]));
3925  plugin->nat
3926  = GNUNET_NAT_register (env->cfg,
3927  "transport-tcp",
3928  IPPROTO_TCP,
3929  (unsigned int) ret_s,
3930  (const struct sockaddr **) addrs,
3931  addrlens,
3934  plugin);
3935  for (ret = ret_s -1; ret >= 0; ret--)
3936  GNUNET_free (addrs[ret]);
3937  GNUNET_free_non_null (addrs);
3938  GNUNET_free_non_null (addrlens);
3939  }
3940  else
3941  {
3942  plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
3943  "transport-tcp",
3944  IPPROTO_TCP,
3945  0,
3946  NULL,
3947  NULL,
3948  NULL,
3950  plugin);
3951  }
3953  api->cls = plugin;
3954  api->send = &tcp_plugin_send;
3968  plugin->service = service;
3969  if (NULL != service)
3970  {
3971  plugin->server = LEGACY_SERVICE_get_server (service);
3972  }
3973  else
3974  {
3975  if (GNUNET_OK !=
3977  "transport-tcp",
3978  "TIMEOUT",
3979  &idle_timeout))
3980  {
3982  "transport-tcp",
3983  "TIMEOUT");
3984  goto die;
3985  }
3986  plugin->server
3988  plugin,
3989  NULL,
3990  idle_timeout,
3991  GNUNET_YES);
3992  }
3993  plugin->handlers = GNUNET_malloc (sizeof (my_handlers));
3994  GNUNET_memcpy (plugin->handlers,
3995  my_handlers,
3996  sizeof(my_handlers));
3997  for (i = 0;i < sizeof(my_handlers) / sizeof(struct GNUNET_SERVER_MessageHandler);i++)
3998  plugin->handlers[i].callback_cls = plugin;
3999 
4001  plugin->handlers);
4003  &connect_notify,
4004  plugin);
4007  plugin);
4009  GNUNET_YES);
4010  if (0 != bport)
4012  _("TCP transport listening on port %llu\n"),
4013  bport);
4014  else
4016  _("TCP transport not listening on any port (client only)\n"));
4017  if ( (aport != bport) &&
4018  (0 != bport) )
4020  _("TCP transport advertises itself as being on port %llu\n"),
4021  aport);
4022  /* Initially set connections to 0 */
4023  GNUNET_STATISTICS_set (plugin->env->stats,
4024  gettext_noop ("# TCP sessions active"),
4025  0,
4026  GNUNET_NO);
4027  return api;
4028 
4029  die:
4030  if (NULL != plugin->nat)
4031  GNUNET_NAT_unregister (plugin->nat);
4033  if (NULL != service)
4034  LEGACY_SERVICE_stop (service);
4035  GNUNET_free (plugin);
4036  GNUNET_free_non_null (api);
4037  return NULL;
4038 }
4039 
4040 
4047 void *
4049 {
4050  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
4051  struct Plugin *plugin = api->cls;
4052  struct TCPProbeContext *tcp_probe;
4053  struct PrettyPrinterContext *cur;
4054  struct PrettyPrinterContext *next;
4055 
4056  if (NULL == plugin)
4057  {
4058  GNUNET_free(api);
4059  return NULL ;
4060  }
4062  "Shutting down TCP plugin\n");
4063 
4064  /* Removing leftover sessions */
4067  plugin);
4068  /* Removing leftover NAT sessions */
4071  plugin);
4072 
4073  for (cur = plugin->ppc_dll_head; NULL != cur; cur = next)
4074  {
4075  next = cur->next;
4077  plugin->ppc_dll_tail,
4078  cur);
4080  cur->asc (cur->asc_cls,
4081  NULL,
4082  GNUNET_OK);
4083  GNUNET_free (cur);
4084  }
4085 
4086  if (NULL != plugin->service)
4087  LEGACY_SERVICE_stop (plugin->service);
4088  else
4089  GNUNET_SERVER_destroy (plugin->server);
4090  GNUNET_free (plugin->handlers);
4091  if (NULL != plugin->nat)
4092  GNUNET_NAT_unregister (plugin->nat);
4093  while (NULL != (tcp_probe = plugin->probe_head))
4094  {
4096  plugin->probe_tail,
4097  tcp_probe);
4098  GNUNET_CONNECTION_destroy (tcp_probe->sock);
4099  GNUNET_free (tcp_probe);
4100  }
4103  GNUNET_break (0 == plugin->cur_connections);
4104  GNUNET_free (plugin);
4105  GNUNET_free (api);
4106  return NULL;
4107 }
4108 
4109 /* end of plugin_transport_tcp.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static unsigned int tcp_plugin_query_keepalive_factor(void *cls)
Function that is called to get the keepalive factor.
size_t address_length
Number of bytes in address.
unsigned long long cur_connections
How many more TCP sessions do we have right now?
struct GNUNET_NAT_Handle * nat
NAT handle & address management.
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:1005
size_t message_size
So that the gnunet-service-transport can group messages together, these pending messages need to acce...
Session is being torn down and about to disappear.
Handle server returns for aborting transmission to a client.
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.
struct GNUNET_NETWORK_Handle * sock
Underlying OS&#39;s socket, set to NULL after fatal errors.
int max_connections
Maximum number of sockets the plugin can use Each http inbound /outbound connections are two connecti...
struct GNUNET_CONTAINER_MultiPeerMap * sessionmap
Map from peer identities to sessions for the given peer.
void GNUNET_SERVER_add_handlers(struct GNUNET_SERVER_Handle *server, const struct GNUNET_SERVER_MessageHandler *handlers)
Add additional handlers to an existing server.
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...
GNUNET_TRANSPORT_TransmitContinuation transmit_cont
Continuation function to call once the message has been sent.
See HTTP_OPTIONS_VERIFY_CERTIFICATE.
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.
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.
Handle for active NAT registrations.
Definition: nat_api.c:72
uint32_t num_bytes_pending
Number of bytes pending transmission for this session.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
GNUNET_TRANSPORT_AddressStringCallback asc
Function to call with the result.
static void handle_tcp_welcome(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message)
We&#39;ve received a welcome from this peer via TCP.
int GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
struct 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.
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
GNUNET_TRANSPORT_AddressToString address_to_string
Function that will be called to convert a binary address to a string (numeric conversion only)...
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_allocate(const struct GNUNET_PeerIdentity *peer, const char *transport_name, const void *address, size_t address_length, enum GNUNET_HELLO_AddressInfo local_info)
Allocate an address struct.
Definition: address.c:73
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct TCPProbeContext * next
Active probes are kept in a DLL.
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
uint64_t rel_value_us
The actual value.
static struct GNUNET_NAT_Handle * nat
Connection to NAT service.
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.
const void * address
Binary representation of the address (plugin-specific).
void * transmit_cont_cls
Closure for transmit_cont.
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:655
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct PrettyPrinterContext * ppc_dll_tail
Running pretty printers: tail.
struct GNUNET_TIME_Absolute receive_delay
When will we continue to read from the socket? (used to enforce inbound quota).
common internal definitions for transport service
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.
unsigned int msgs_in_queue
Number of messages waiting for transmission to this peer.
GNUNET_SERVER_MessageCallback callback
Function to call for messages of "type".
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
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.
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.
struct GNUNET_SCHEDULER_Task * timeout_task
Session timeout task.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
uint16_t open_port
Port that we are actually listening on.
struct TCPProbeContext * probe_head
List of active TCP probes.
struct Plugin * plugin
Pointer to the global plugin struct.
struct GNUNET_SERVER_Client * client
The client (used to identify this connection)
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
GNUNET_TRANSPORT_DisconnectPeerFunction disconnect_peer
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
static unsigned long long max_connections
If there are at least this many connections, old ones will be removed.
struct GNUNET_SERVER_TransmitHandle * transmit_handle
Handle for pending transmission request.
Do not trigger server shutdown on signal at all; instead, allow for the user to terminate the server ...
int is_inbound
GNUNET_YES if this is an inbound connection, GNUNET_NO if this is an outbound connection, GNUNET_SYSERR if connections of this plugin are so fundamentally bidirectional that they have no &#39;initiator&#39;
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:245
enum GNUNET_TRANSPORT_SessionState state
New state of the session.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_RESOLVER_RequestHandle * resolver_handle
Resolver handle.
struct GNUNET_SCHEDULER_Task * nat_connection_timeout
Task cleaning up a NAT client connection establishment attempt;.
int is_nat
Was this session created using NAT traversal?
#define STRERROR(i)
Definition: plibc.h:676
GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
uid_t uid
UID of the other end of the connection.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
GNUNET_TRANSPORT_SessionMonitorSetup setup_monitor
Function to monitor the sessions managed by the plugin.
struct GNUNET_SCHEDULER_Task * receive_delay_task
ID of task used to delay receiving more to throttle sender.
Initial session handshake is in progress.
Closure for append_port().
static void delayed_done(void *cls)
Task to signal the server that we can continue receiving from the TCP client now. ...
uint16_t port
Port to add after the IP address.
void GNUNET_SERVER_client_drop(struct GNUNET_SERVER_Client *client)
Notify the server that the given client handle is no longer required.
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.
const struct GNUNET_PeerIdentity * my_identity
Identity of this peer.
struct PendingMessage * next
DLL next, prev.
struct GNUNET_TIME_Absolute timeout
When does this session time out.
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:833
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
void GNUNET_SERVER_notify_transmit_ready_cancel(struct GNUNET_SERVER_TransmitHandle *th)
Abort transmission request.
#define GNUNET_NO
Definition: gnunet_common.h:81
static int numeric
Option -n.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
void GNUNET_SERVER_mst_destroy(struct GNUNET_SERVER_MessageStreamTokenizer *mst)
Destroys a tokenizer.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_HELLO_Address * address
Address.
uint32_t options
Optional flags for this address see enum TcpAddressOptions
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.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
const struct GNUNET_HELLO_Address * address
Address used by the session.
unsigned long long bytes_in_queue
Number of bytes waiting for transmission to this peer.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_get(const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls)
Perform a reverse DNS lookup.
void * asc_cls
Clsoure for asc.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
uint64_t abs_value_us
The actual value.
void GNUNET_SERVER_client_disconnect(struct GNUNET_SERVER_Client *client)
Ask the server to disconnect from the given client.
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:35
uint32_t num_msg_pending
Number of messages pending transmission for this session.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
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...
struct GNUNET_SCHEDULER_Task * address_update_task
ID of task used to update our addresses when one expires.
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
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.
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...
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
static void append_port(void *cls, const char *hostname)
We are processing an address pretty printing request and finished the IP resolution (if applicable)...
int cur_connections
Current number of establishes connections.
struct GNUNET_TIME_Absolute receive_delay
Until when does this plugin refuse to receive to manage staying within the inbound quota...
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
struct TCPProbeContext * probe_tail
List of active TCP probes.
int GNUNET_NAT_test_address(struct GNUNET_NAT_Handle *nh, const void *addr, socklen_t addrlen)
Test if the given address is (currently) a plausible IP address for this peer.
Definition: nat_api.c:623
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 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(* LEGACY_SERVICE_Main)(void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg)
Function called by the service&#39;s run method to run service-specific setup code.
Handle to a message stream tokenizer.
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.
gid_t gid
GID of the other end of the connection.
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.
GNUNET_TRANSPORT_PluginReceiveCallback receive
Function that should be called by the transport plugin whenever a message is received.
struct GNUNET_ATS_Session * result
Where to store the session (if we found it).
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.
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
GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout
Function that will be called whenever the transport service wants to notify the plugin that a session...
static struct GNUNET_ATS_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 struct GNUNET_ATS_SolverFunctions * plugin
Our solver.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
Information about a plugin&#39;s session.
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 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.
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.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
struct PendingMessage * pending_messages_tail
Messages currently pending for transmission to this peer, if any.
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:130
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.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
Network format for IPv4 addresses.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint32_t options
Optional options and flags for this address, see enum TcpAddressOptions
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...
void * cls
Closure for the various callbacks.
enum State state
current state of profiling
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
void * cls
Closure for all of the callbacks.
#define GNUNET_memcpy(dst, src, n)
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_setup_monitor(void *cls, GNUNET_TRANSPORT_SessionInfoCallback sic, void *sic_cls)
Begin monitoring sessions of a plugin.
struct Plugin * plugin
Transport plugin handle.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
static char * value
Value of the record to add/remove.
void(* GNUNET_TRANSPORT_AddressStringCallback)(void *cls, const char *address, int res)
Function called by the pretty printer for the resolved address for each human-readable address obtain...
void GNUNET_SERVER_resume(struct GNUNET_SERVER_Handle *server)
Resume accepting connections from the listen socket.
#define GNUNET_SERVER_client_get_user_context(client, type)
Return user context associated with the given client.
GNUNET_TRANSPORT_StringToAddress string_to_address
Function that will be called to convert a string address to binary (numeric conversion only)...
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
Information about ongoing sessions of the transport client.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
This is an inbound address and cannot be used to initiate an outbound connection to another peer...
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
static struct GNUNET_SCHEDULER_Task * t4
Task for IPv4 socket.
The transport service will pass a pointer to a struct of this type as the first and only argument to ...
static enum GNUNET_NetworkType scope
Which network scope do we belong to?
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
struct PrettyPrinterContext * prev
DLL.
struct PendingMessage * pending_messages_head
Messages currently pending for transmission to this peer, if any.
int 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.
void LEGACY_SERVICE_stop(struct LEGACY_SERVICE_Context *srv)
Stops a service that was started with GNUNET_SERVICE_start().
GNUNET_TRANSPORT_GetNetworkType get_network
Function to obtain the network type for a session.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:727
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:51
uint16_t adv_port
Port that the user said we would have visible to the rest of the world.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME
Welcome message between TCP transports.
static char buf[2048]
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 ...
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_CONTAINER_DLL_insert_after(head, tail, other, element)
Insert an element into a DLL after the given other element.
handle for a server
TcpAddressOptions
Bits in the options field of TCP addresses.
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...
struct GNUNET_CONNECTION_Handle * connection
Client closure for callbacks.
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)...
Context for sending a NAT probe via TCP.
struct GNUNET_TIME_Absolute session_timeout
At what time will this session timeout (unless activity happens)?
Internal representation of the hash map.
struct TransportClient * client
Client that issued the transmission request, if pmt is PMT_CORE.
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.
void GNUNET_SERVER_client_set_timeout(struct GNUNET_SERVER_Client *client, struct GNUNET_TIME_Relative timeout)
Change the timeout for a particular client.
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.
LEGACY_SERVICE_Options
Options for the service (bitmask).
Closure for session_lookup_it().
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
GNUNET_TRANSPORT_UpdateInboundDelay update_inbound_delay
Function that will be called whenever the transport service wants to notify the plugin that the inbou...
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.
uint16_t expected_size
Expected size of messages of this type.
struct GNUNET_CONNECTION_Handle * sock
Probe connection.
static int res
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
void GNUNET_SERVER_suspend(struct GNUNET_SERVER_Handle *server)
Suspend accepting connections from the listen socket temporarily.
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_TIME_Absolute timeout
At what time should we give up on the transmission (and no longer retry)?
struct GNUNET_SERVER_Handle * LEGACY_SERVICE_get_server(struct LEGACY_SERVICE_Context *ctx)
Obtain the server used by a service.
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
Network format for IPv6 addresses.
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...
struct GNUNET_CONNECTION_Handle * lsock
The listen socket.
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...
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition: nat_api.c:690
const struct GNUNET_HELLO_Address * address
Address we are looking for.
struct PendingMessage * prev
This is a doubly-linked list.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct TCPProbeContext * prev
Active probes are kept in a DLL.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
struct GNUNET_PeerIdentity clientIdentity
Identity of the node connecting (TCP client)
static unsigned int size
Size of the "table".
Definition: peer.c:67
struct GNUNET_PeerIdentity clientIdentity
Identity of the sender of the message.
struct in6_addr ipv6_addr
IPv6 address.
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...
Handle to a request given to the resolver.
Definition: resolver_api.c:100
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.
uint16_t type
Type of the message this handler covers.
enum GNUNET_NetworkType scope
ATS network type.
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition: nat_api.c:378
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
void(* GNUNET_TRANSPORT_TransmitContinuation)(void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire)
Function called by the GNUNET_TRANSPORT_TransmitFunction upon "completion".
void GNUNET_CONNECTION_destroy(struct GNUNET_CONNECTION_Handle *connection)
Close the connection and free associated resources.
struct Plugin * plugin
Our plugin.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static struct GNUNET_SCHEDULER_Task * timeout_task
Task to be run on timeout.
Definition: gnunet-arm.c:119
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_NETWORK_Handle *const * LEGACY_SERVICE_get_listen_sockets(struct LEGACY_SERVICE_Context *ctx)
Get the NULL-terminated array of listen sockets for this service.
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
struct PrettyPrinterContext * next
DLL.
static int session_lookup_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Look for a session by address.
struct GNUNET_PeerIdentity peer
For which peer is this an address?
int GNUNET_SERVER_client_get_address(struct GNUNET_SERVER_Client *client, void **addr, size_t *addrlen)
Obtain the network address of the other party.
int expecting_welcome
Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO)
static void handle_tcp_data(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message)
We&#39;ve received data for this peer via TCP.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
#define GNUNET_SERVER_client_set_user_context(client, value)
Set user context to be associated with the given client.
Allow multiple values with the same key.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don&#39;t receive messages from the peer...
static void disconnect_notify(void *cls, struct GNUNET_SERVER_Client *client)
Function called whenever a peer is disconnected on the "SERVER" level.
#define PLUGIN_NAME
GNUNET_CONNECTION_TransmitReadyNotify callback
Function to call to get the message.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
This is just an update about the session, the state did not change.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
static void connect_notify(void *cls, struct GNUNET_SERVER_Client *client)
Function called whenever a peer is connected on the "SERVER" level.
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.
#define GNUNET_MESSAGE_TYPE_ALL
Next available: 1500.
void(* GNUNET_SERVER_MstDestroyCallback)(void *cls, void *mst)
Signature of a function to destroy a custom tokenizer.
GNUNET_TRANSPORT_QueryKeepaliveFactorFunction query_keepalive_factor
Function that is used to query keepalive factor.
The identity of the host (wraps the signing key of the peer).
No additional information.
GNUNET_SERVER_MessageTokenizerCallback cb
Function to call on completed messages.
int GNUNET_CONTAINER_multipeermap_contains_value(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Check if the map contains the given value under the given key.
static void process_pending_messages(struct GNUNET_ATS_Session *session)
If we have pending messages, ask the server to transmit them (schedule the respective tasks...
void * libgnunet_plugin_transport_tcp_done(void *cls)
Exit point from the plugin.
static char * hostname
Our hostname; we give this to all the peers we start.
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.
#define GNUNET_PACKED
gcc-ism to get packed structs.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:79
static void session_timeout(void *cls)
Session was idle for too long, so disconnect it.
configuration data
Definition: configuration.c:85
Handle for a plugin.
Definition: block.c:37
uint32_t options
Address options.
Context for "service_task".
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_PeerIdentity target
To whom are we talking to.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE
TCP NAT probe message, send from NAT&#39;d peer to other peer to establish bi-directional communication...
Initial handshake message for a session.
void * callback_cls
Closure for callback.
An address for communicating with a peer.
struct WelcomeMessage my_welcome
Welcome message used by this peer.
struct TCP_NAT_ProbeMessage message
Message to be sent.
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.
struct GNUNET_CONNECTION_TransmitHandle * transmit_handle
Handle to the transmission.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:109
#define GNUNET_log(kind,...)
The session was created (first call for each session object).
Entry in list of pending tasks.
Definition: scheduler.c:134
void GNUNET_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.
void GNUNET_SERVER_receive_done(struct GNUNET_SERVER_Client *client, int success)
Resume receiving from this client, we are done processing the current request.
void * libgnunet_plugin_transport_tcp_init(void *cls)
Entry point for the plugin.
List containing all messages that are yet to be send.
uint16_t t4_port
Port number, in network byte order.
Credentials for UNIX domain sockets.
const char * msg
The pending message.
struct GNUNET_SERVER_MessageHandler * handlers
Copy of the handler array where the closures are set to this struct&#39;s instance.
int 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.
handle to a socket
Definition: network.c:46
struct Client * client
The transport client that provided the session.
static void handle_tcp_nat_probe(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message)
We&#39;ve received a nat probe from this peer via TCP.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
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:157
void * cls
Closure to use for callbacks.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
GNUNET_TRANSPORT_AddressPrettyPrinter address_pretty_printer
Function to pretty-print addresses.
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
struct GNUNET_CONTAINER_MultiPeerMap * nat_wait_conns
Map of peers we have tried to contact behind a NAT.
#define NAT_TIMEOUT
How long until we give up on establishing an NAT connection? Must be > 4 RTT.
struct GNUNET_TIME_Absolute last_activity
Last activity on this connection.
handle for a client of the server
unsigned long long max_connections
How many more TCP sessions are we allowed to open right now?
struct PrettyPrinterContext * ppc_dll_head
Running pretty printers: head.
Enable TCP Stealth-style port knocking.
uint32_t ipv4_addr
IPv4 address, in network byte order.
uint32_t myoptions
Address options.
GNUNET_TRANSPORT_CheckAddress check_address
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
struct LEGACY_SERVICE_Context * service
Handle to the network service.
GNUNET_TRANSPORT_SessionState
Possible states of a session in a plugin.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
#define LOG(kind,...)
handle for a network connection
int 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)...
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 char * address
GNS address for this phone.
struct GNUNET_SERVER_Handle * server
Handle to the server for this service.
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...
void * mst
Processing of incoming data.
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.
Basically a WELCOME message, but with the purpose of giving the waiting peer a client handle to use...
void * callback_cls
Closure argument for callback.
void GNUNET_SERVER_destroy(struct GNUNET_SERVER_Handle *server)
Free resources held by this server.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
static enum GNUNET_NetworkType tcp_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
Function obtain the network type for a session.
#define GNUNET_HELLO_address_free(addr)
Free an address.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:604
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_STRINGS_to_address_ip(const char *addr, uint16_t addrlen, struct sockaddr_storage *r_buf)
Tries to convert addr string to an IP (v4 or v6) address.
Definition: strings.c:1409
void * sic_cls
Closure for sic.
#define GNUNET_malloc(size)
Wrapper around malloc.
uint16_t t6_port
Port number, in network byte order.
static void reschedule_session_timeout(struct GNUNET_ATS_Session *s)
Increment session timeout due to activity.
struct GNUNET_SERVER_MessageStreamTokenizer * GNUNET_SERVER_mst_create(GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
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_ConnectCallback)(void *cls, struct GNUNET_SERVER_Client *client)
Functions with this signature are called whenever a client is connected on the network level...
static struct GNUNET_SCHEDULER_Task * t6
Task for IPv6 socket.
GNUNET_TRANSPORT_GetNetworkTypeForAddress get_network_for_address
Function to obtain the network type for an address.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static struct GNUNET_TRANSPORT_PluginMonitor * pm
Handle if we are monitoring plugin session activity.
#define gettext_noop(String)
Definition: gettext.h:69
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:1037
Category of last resort.
Definition: gnunet_nt_lib.h:40
static void nat_connect_timeout(void *cls)
Task cleaning up a NAT connection attempt after timeout.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965