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 
99 typedef size_t (*GNUNET_CONNECTION_TransmitReadyNotify) (void *cls,
100  size_t size,
101  void *buf);
102 
110  uid_t uid;
111 
115  gid_t gid;
116 };
117 
118 
128  void *cls,
129  struct GNUNET_SERVER_Client *client);
130 
131 
140  void *cls,
141  struct GNUNET_SERVER_Client *client);
142 
143 
155  void *cls,
156  const struct GNUNET_CONNECTION_Credentials *ucred,
157  const struct sockaddr *addr,
158  socklen_t addrlen);
159 
172 typedef void (*GNUNET_CONNECTION_Receiver) (void *cls,
173  const void *buf,
174  size_t available,
175  const struct sockaddr *addr,
176  socklen_t addrlen,
177  int errCode);
178 
179 
187 void
189 
190 
198 typedef void *(*GNUNET_SERVER_MstCreateCallback) (
199  void *cls,
200  struct GNUNET_SERVER_Client *client);
201 
202 
209 typedef void (*GNUNET_SERVER_MstDestroyCallback) (void *cls, void *mst);
210 
228  void *cls,
229  void *mst,
230  struct GNUNET_SERVER_Client *client,
231  const char *buf,
232  size_t size,
233  int purge,
234  int one_shot);
244  void *cls,
245  struct GNUNET_SERVER_Client *client,
246  const struct GNUNET_MessageHeader *message);
247 
257 
262 
266  uint16_t type;
267 
274  uint16_t expected_size;
275 };
276 
277 
287 
294 
300 };
301 
302 
311 void
313 
322 void *
324  size_t size);
325 
326 
340  void *cls,
341  void *client,
342  const struct GNUNET_MessageHeader *message);
343 
344 
354  void *cb_cls);
355 
372 int
374  void *client_identity,
375  const char *buf,
376  size_t size,
377  int purge,
378  int one_shot);
379 
380 
386 void
388 
389 
398 void
400  void *ptr,
401  size_t size);
409 #define GNUNET_SERVER_client_get_user_context(client, type) \
410  (type *)GNUNET_SERVER_client_get_user_context_(client, sizeof(type))
411 
418 #define GNUNET_SERVER_client_set_user_context(client, value) \
419  GNUNET_SERVER_client_set_user_context_(client, value, sizeof(*value))
420 
421 
439  struct GNUNET_SERVER_Client *client,
440  size_t size,
443  void *callback_cls);
444 
450 void
452  struct GNUNET_SERVER_TransmitHandle *th);
453 
454 
462 void
464 
465 
474 void
476 
477 
486 typedef void (*LEGACY_SERVICE_Main) (
487  void *cls,
488  struct GNUNET_SERVER_Handle *server,
489  const struct GNUNET_CONFIGURATION_Handle *cfg);
490 
491 
498 void
500 
518  struct GNUNET_SERVER_Client *client,
519  size_t size,
522  void *callback_cls);
523 
524 
536 struct GNUNET_SERVER_Client *
539 
540 
546 void
548 
554 void
556 
557 
558 #include "tcp_connection_legacy.c"
559 #include "tcp_server_mst_legacy.c"
560 #include "tcp_server_legacy.c"
561 #include "tcp_service_legacy.c"
562 
564 
572  struct GNUNET_MessageHeader header;
573 
577  struct GNUNET_PeerIdentity clientIdentity;
578 };
579 
588  struct GNUNET_MessageHeader header;
589 
593  struct GNUNET_PeerIdentity clientIdentity;
594 };
596 
605 
610 
615 
619  struct TCP_NAT_ProbeMessage message;
620 
625 
629  struct Plugin *plugin;
630 };
631 
640 
645 
650 };
651 
653 
663 
667  uint32_t ipv4_addr GNUNET_PACKED;
668 
672  uint16_t t4_port GNUNET_PACKED;
673 };
674 
684 
688  struct in6_addr ipv6_addr GNUNET_PACKED;
689 
693  uint16_t t6_port GNUNET_PACKED;
694 };
696 
700 struct Plugin;
701 
706 struct PendingMessage {
710  struct PendingMessage *next;
711 
715  struct PendingMessage *prev;
716 
720  const char *msg;
721 
728 
733 
738 
744  size_t message_size;
745 };
746 
750 struct GNUNET_ATS_Session {
755  struct GNUNET_PeerIdentity target;
756 
760  struct Plugin *plugin;
761 
766 
771 
777 
783 
788 
793 
798 
803 
808 
813  struct GNUNET_TIME_Absolute receive_delay;
814 
819  struct GNUNET_TIME_Absolute last_activity;
820 
824  unsigned long long bytes_in_queue;
825 
829  unsigned int msgs_in_queue;
830 
835 
840 
844  int is_nat;
845 };
846 
847 
852 struct PrettyPrinterContext {
856  struct PrettyPrinterContext *next;
857 
861  struct PrettyPrinterContext *prev;
862 
866  struct Plugin *plugin;
867 
872 
876  struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
877 
882 
886  void *asc_cls;
887 
891  int ipv6;
892 
896  uint32_t options;
897 
901  uint16_t port;
902 };
903 
904 
908 struct Plugin {
913 
918 
922  struct GNUNET_NAT_Handle *nat;
923 
928 
933 
938 
944 
949 
954 
959 
964 
968  void *sic_cls;
969 
974 
979 
984 
988  struct WelcomeMessage my_welcome;
989 
993  unsigned long long max_connections;
994 
998  unsigned long long cur_connections;
999 
1003  uint32_t myoptions;
1004 
1008  uint16_t open_port;
1009 
1014  uint16_t adv_port;
1015 };
1016 
1017 
1038 static int
1040  const struct GNUNET_CONFIGURATION_Handle *cfg,
1041  struct sockaddr ***addrs,
1042  socklen_t **addr_lens)
1043 {
1044  int disablev6;
1045  struct GNUNET_NETWORK_Handle *desc;
1046  unsigned long long port;
1047  char *unixpath;
1048  struct addrinfo hints;
1049  struct addrinfo *res;
1050  struct addrinfo *pos;
1051  struct addrinfo *next;
1052  unsigned int i;
1053  int resi;
1054  int ret;
1055  int abstract;
1056  struct sockaddr **saddrs;
1057  socklen_t *saddrlens;
1058  char *hostname;
1059 
1060  *addrs = NULL;
1061  *addr_lens = NULL;
1062  desc = NULL;
1063  if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "DISABLEV6"))
1064  {
1065  if (GNUNET_SYSERR ==
1066  (disablev6 = GNUNET_CONFIGURATION_get_value_yesno(cfg,
1067  service_name,
1068  "DISABLEV6")))
1069  return GNUNET_SYSERR;
1070  }
1071  else
1072  disablev6 = GNUNET_NO;
1073 
1074  if (!disablev6)
1075  {
1076  /* probe IPv6 support */
1077  desc = GNUNET_NETWORK_socket_create(PF_INET6, SOCK_STREAM, 0);
1078  if (NULL == desc)
1079  {
1080  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1081  (EACCES == errno))
1082  {
1084  return GNUNET_SYSERR;
1085  }
1087  _(
1088  "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
1089  service_name,
1090  strerror(errno));
1091  disablev6 = GNUNET_YES;
1092  }
1093  else
1094  {
1096  desc = NULL;
1097  }
1098  }
1099 
1100  port = 0;
1101  if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "PORT"))
1102  {
1104  service_name,
1105  "PORT",
1106  &port))
1107  {
1109  _("Require valid port number for service `%s' in configuration!\n"),
1110  service_name);
1111  }
1112  if (port > 65535)
1113  {
1115  _("Require valid port number for service `%s' in configuration!\n"),
1116  service_name);
1117  return GNUNET_SYSERR;
1118  }
1119  }
1120 
1121  if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "BINDTO"))
1122  {
1125  service_name,
1126  "BINDTO",
1127  &hostname));
1128  }
1129  else
1130  hostname = NULL;
1131 
1132  unixpath = NULL;
1133  abstract = GNUNET_NO;
1134 #ifdef AF_UNIX
1135  if ((GNUNET_YES ==
1136  GNUNET_CONFIGURATION_have_value(cfg, service_name, "UNIXPATH")) &&
1138  service_name,
1139  "UNIXPATH",
1140  &unixpath)) &&
1141  (0 < strlen(unixpath)))
1142  {
1143  /* probe UNIX support */
1144  struct sockaddr_un s_un;
1145 
1146  if (strlen(unixpath) >= sizeof(s_un.sun_path))
1147  {
1149  _("UNIXPATH `%s' too long, maximum length is %llu\n"),
1150  unixpath,
1151  (unsigned long long)sizeof(s_un.sun_path));
1152  unixpath = GNUNET_NETWORK_shorten_unixpath(unixpath);
1153  LOG(GNUNET_ERROR_TYPE_INFO, _("Using `%s' instead\n"), unixpath);
1154  }
1155 #ifdef LINUX
1156  abstract = GNUNET_CONFIGURATION_get_value_yesno(cfg,
1157  "TESTING",
1158  "USE_ABSTRACT_SOCKETS");
1159  if (GNUNET_SYSERR == abstract)
1160  abstract = GNUNET_NO;
1161 #endif
1162  if ((GNUNET_YES != abstract) &&
1165  }
1166  if (NULL != unixpath)
1167  {
1168  desc = GNUNET_NETWORK_socket_create(AF_UNIX, SOCK_STREAM, 0);
1169  if (NULL == desc)
1170  {
1171  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1172  (EACCES == errno))
1173  {
1175  GNUNET_free_non_null(hostname);
1176  GNUNET_free(unixpath);
1177  return GNUNET_SYSERR;
1178  }
1180  _(
1181  "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1182  service_name,
1183  strerror(errno));
1184  GNUNET_free(unixpath);
1185  unixpath = NULL;
1186  }
1187  else
1188  {
1190  desc = NULL;
1191  }
1192  }
1193 #endif
1194 
1195  if ((0 == port) && (NULL == unixpath))
1196  {
1198  _(
1199  "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1200  service_name);
1201  GNUNET_free_non_null(hostname);
1202  return GNUNET_SYSERR;
1203  }
1204  if (0 == port)
1205  {
1206  saddrs = GNUNET_malloc(2 * sizeof(struct sockaddr *));
1207  saddrlens = GNUNET_malloc(2 * sizeof(socklen_t));
1208  add_unixpath(saddrs, saddrlens, unixpath, abstract);
1209  GNUNET_free_non_null(unixpath);
1210  GNUNET_free_non_null(hostname);
1211  *addrs = saddrs;
1212  *addr_lens = saddrlens;
1213  return 1;
1214  }
1215 
1216  if (NULL != hostname)
1217  {
1219  "Resolving `%s' since that is where `%s' will bind to.\n",
1220  hostname,
1221  service_name);
1222  memset(&hints, 0, sizeof(struct addrinfo));
1223  if (disablev6)
1224  hints.ai_family = AF_INET;
1225  hints.ai_protocol = IPPROTO_TCP;
1226  if ((0 != (ret = getaddrinfo(hostname, NULL, &hints, &res))) ||
1227  (NULL == res))
1228  {
1230  _("Failed to resolve `%s': %s\n"),
1231  hostname,
1232  gai_strerror(ret));
1233  GNUNET_free(hostname);
1234  GNUNET_free_non_null(unixpath);
1235  return GNUNET_SYSERR;
1236  }
1237  next = res;
1238  i = 0;
1239  while (NULL != (pos = next))
1240  {
1241  next = pos->ai_next;
1242  if ((disablev6) && (pos->ai_family == AF_INET6))
1243  continue;
1244  i++;
1245  }
1246  if (0 == i)
1247  {
1249  _("Failed to find %saddress for `%s'.\n"),
1250  disablev6 ? "IPv4 " : "",
1251  hostname);
1252  freeaddrinfo(res);
1253  GNUNET_free(hostname);
1254  GNUNET_free_non_null(unixpath);
1255  return GNUNET_SYSERR;
1256  }
1257  resi = i;
1258  if (NULL != unixpath)
1259  resi++;
1260  saddrs = GNUNET_malloc((resi + 1) * sizeof(struct sockaddr *));
1261  saddrlens = GNUNET_malloc((resi + 1) * sizeof(socklen_t));
1262  i = 0;
1263  if (NULL != unixpath)
1264  {
1265  add_unixpath(saddrs, saddrlens, unixpath, abstract);
1266  i++;
1267  }
1268  next = res;
1269  while (NULL != (pos = next))
1270  {
1271  next = pos->ai_next;
1272  if ((disablev6) && (AF_INET6 == pos->ai_family))
1273  continue;
1274  if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1275  continue; /* not TCP */
1276  if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1277  continue; /* huh? */
1279  "Service `%s' will bind to `%s'\n",
1280  service_name,
1281  GNUNET_a2s(pos->ai_addr, pos->ai_addrlen));
1282  if (AF_INET == pos->ai_family)
1283  {
1284  GNUNET_assert(sizeof(struct sockaddr_in) == pos->ai_addrlen);
1285  saddrlens[i] = pos->ai_addrlen;
1286  saddrs[i] = GNUNET_malloc(saddrlens[i]);
1287  GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
1288  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
1289  }
1290  else
1291  {
1292  GNUNET_assert(AF_INET6 == pos->ai_family);
1293  GNUNET_assert(sizeof(struct sockaddr_in6) == pos->ai_addrlen);
1294  saddrlens[i] = pos->ai_addrlen;
1295  saddrs[i] = GNUNET_malloc(saddrlens[i]);
1296  GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
1297  ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
1298  }
1299  i++;
1300  }
1301  GNUNET_free(hostname);
1302  freeaddrinfo(res);
1303  resi = i;
1304  }
1305  else
1306  {
1307  /* will bind against everything, just set port */
1308  if (disablev6)
1309  {
1310  /* V4-only */
1311  resi = 1;
1312  if (NULL != unixpath)
1313  resi++;
1314  i = 0;
1315  saddrs = GNUNET_malloc((resi + 1) * sizeof(struct sockaddr *));
1316  saddrlens = GNUNET_malloc((resi + 1) * sizeof(socklen_t));
1317  if (NULL != unixpath)
1318  {
1319  add_unixpath(saddrs, saddrlens, unixpath, abstract);
1320  i++;
1321  }
1322  saddrlens[i] = sizeof(struct sockaddr_in);
1323  saddrs[i] = GNUNET_malloc(saddrlens[i]);
1324 #if HAVE_SOCKADDR_IN_SIN_LEN
1325  ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[i];
1326 #endif
1327  ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
1328  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
1329  }
1330  else
1331  {
1332  /* dual stack */
1333  resi = 2;
1334  if (NULL != unixpath)
1335  resi++;
1336  saddrs = GNUNET_malloc((resi + 1) * sizeof(struct sockaddr *));
1337  saddrlens = GNUNET_malloc((resi + 1) * sizeof(socklen_t));
1338  i = 0;
1339  if (NULL != unixpath)
1340  {
1341  add_unixpath(saddrs, saddrlens, unixpath, abstract);
1342  i++;
1343  }
1344  saddrlens[i] = sizeof(struct sockaddr_in6);
1345  saddrs[i] = GNUNET_malloc(saddrlens[i]);
1346 #if HAVE_SOCKADDR_IN_SIN_LEN
1347  ((struct sockaddr_in6 *)saddrs[i])->sin6_len = saddrlens[0];
1348 #endif
1349  ((struct sockaddr_in6 *)saddrs[i])->sin6_family = AF_INET6;
1350  ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
1351  i++;
1352  saddrlens[i] = sizeof(struct sockaddr_in);
1353  saddrs[i] = GNUNET_malloc(saddrlens[i]);
1354 #if HAVE_SOCKADDR_IN_SIN_LEN
1355  ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[1];
1356 #endif
1357  ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
1358  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
1359  }
1360  }
1361  GNUNET_free_non_null(unixpath);
1362  *addrs = saddrs;
1363  *addr_lens = saddrlens;
1364  return resi;
1365 }
1366 /* end ancient copy-and-paste */
1367 
1368 
1377 static void
1379  struct GNUNET_ATS_Session *session,
1381 {
1382  struct GNUNET_TRANSPORT_SessionInfo info;
1383 
1384  if (NULL == plugin->sic)
1385  return;
1386  memset(&info, 0, sizeof(info));
1387  info.state = state;
1388  info.is_inbound =
1391  info.num_msg_pending = session->msgs_in_queue;
1392  info.num_bytes_pending = session->bytes_in_queue;
1393  if (NULL != session->receive_delay_task)
1394  info.receive_delay = session->receive_delay;
1395  info.session_timeout = session->timeout;
1396  info.address = session->address;
1397  plugin->sic(plugin->sic_cls, session, &info);
1398 }
1399 
1400 
1413 static void
1415  void **app_ctx,
1416  int add_remove,
1418  const struct sockaddr *addr,
1419  socklen_t addrlen)
1420 {
1421  struct Plugin *plugin = cls;
1422  struct GNUNET_HELLO_Address *address;
1423  struct IPv4TcpAddress t4;
1424  struct IPv6TcpAddress t6;
1425  void *arg;
1426  size_t args;
1427 
1428  (void)app_ctx;
1430  "NAT notification to %s address `%s'\n",
1431  (GNUNET_YES == add_remove) ? "add" : "remove",
1432  GNUNET_a2s(addr, addrlen));
1433  /* convert 'addr' to our internal format */
1434  switch (addr->sa_family)
1435  {
1436  case AF_INET:
1437  GNUNET_assert(addrlen == sizeof(struct sockaddr_in));
1438  memset(&t4, 0, sizeof(t4));
1439  t4.options = htonl(plugin->myoptions);
1440  t4.ipv4_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
1441  t4.t4_port = ((struct sockaddr_in *)addr)->sin_port;
1442  arg = &t4;
1443  args = sizeof(t4);
1444  break;
1445 
1446  case AF_INET6:
1447  if (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)addr)->sin6_addr))
1448  {
1449  /* skip link local, we don't allow them in
1450  #tcp_plugin_check_address() */
1451  return;
1452  }
1453  GNUNET_assert(addrlen == sizeof(struct sockaddr_in6));
1454  memset(&t6, 0, sizeof(t6));
1456  &((struct sockaddr_in6 *)addr)->sin6_addr,
1457  sizeof(struct in6_addr));
1458  t6.options = htonl(plugin->myoptions);
1459  t6.t6_port = ((struct sockaddr_in6 *)addr)->sin6_port;
1460  arg = &t6;
1461  args = sizeof(t6);
1462  break;
1463 
1464  default:
1465  GNUNET_break(0);
1466  return;
1467  }
1468  /* modify our published address list */
1469  GNUNET_assert((args == sizeof(struct IPv4TcpAddress)) ||
1470  (args == sizeof(struct IPv6TcpAddress)));
1471  /* TODO: use 'ac' here in the future... */
1472  address = GNUNET_HELLO_address_allocate(plugin->env->my_identity,
1473  PLUGIN_NAME,
1474  arg,
1475  args,
1477  plugin->env->notify_address(plugin->env->cls, add_remove, address);
1478  GNUNET_HELLO_address_free(address);
1479 }
1480 
1481 
1493 static const char *
1494 tcp_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
1495 {
1496  static char rbuf[INET6_ADDRSTRLEN + 12];
1497  char buf[INET6_ADDRSTRLEN];
1498  const void *sb;
1499  struct in_addr a4;
1500  struct in6_addr a6;
1501  const struct IPv4TcpAddress *t4;
1502  const struct IPv6TcpAddress *t6;
1503  int af;
1504  uint16_t port;
1505  uint32_t options;
1506 
1507  switch (addrlen)
1508  {
1509  case sizeof(struct IPv6TcpAddress):
1510  t6 = addr;
1511  af = AF_INET6;
1512  port = ntohs(t6->t6_port);
1513  options = ntohl(t6->options);
1514  GNUNET_memcpy(&a6, &t6->ipv6_addr, sizeof(a6));
1515  sb = &a6;
1516  break;
1517 
1518  case sizeof(struct IPv4TcpAddress):
1519  t4 = addr;
1520  af = AF_INET;
1521  port = ntohs(t4->t4_port);
1522  options = ntohl(t4->options);
1523  GNUNET_memcpy(&a4, &t4->ipv4_addr, sizeof(a4));
1524  sb = &a4;
1525  break;
1526 
1527  default:
1528  LOG(GNUNET_ERROR_TYPE_WARNING,
1529  _("Unexpected address length: %u bytes\n"),
1530  (unsigned int)addrlen);
1531  return NULL;
1532  }
1533  if (NULL == inet_ntop(af, sb, buf, INET6_ADDRSTRLEN))
1534  {
1536  return NULL;
1537  }
1538  GNUNET_snprintf(rbuf,
1539  sizeof(rbuf),
1540  (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u",
1541  PLUGIN_NAME,
1542  options,
1543  buf,
1544  port);
1545  return rbuf;
1546 }
1547 
1548 
1561 static int
1563  const char *addr,
1564  uint16_t addrlen,
1565  void **buf,
1566  size_t *added)
1567 {
1568  struct sockaddr_storage socket_address;
1569  char *address;
1570  char *plugin;
1571  char *optionstr;
1572  uint32_t options;
1573 
1574  /* Format tcp.options.address:port */
1575  address = NULL;
1576  plugin = NULL;
1577  optionstr = NULL;
1578  if ((NULL == addr) || (0 == addrlen))
1579  {
1580  GNUNET_break(0);
1581  return GNUNET_SYSERR;
1582  }
1583  if ('\0' != addr[addrlen - 1])
1584  {
1585  GNUNET_break(0);
1586  return GNUNET_SYSERR;
1587  }
1588  if (strlen(addr) != addrlen - 1)
1589  {
1590  GNUNET_break(0);
1591  return GNUNET_SYSERR;
1592  }
1593  plugin = GNUNET_strdup(addr);
1594  optionstr = strchr(plugin, '.');
1595  if (NULL == optionstr)
1596  {
1597  GNUNET_break(0);
1598  GNUNET_free(plugin);
1599  return GNUNET_SYSERR;
1600  }
1601  optionstr[0] = '\0';
1602  optionstr++;
1603  options = atol(optionstr);
1604  address = strchr(optionstr, '.');
1605  if (NULL == address)
1606  {
1607  GNUNET_break(0);
1608  GNUNET_free(plugin);
1609  return GNUNET_SYSERR;
1610  }
1611  address[0] = '\0';
1612  address++;
1613 
1614  if (GNUNET_OK !=
1615  GNUNET_STRINGS_to_address_ip(address, strlen(address), &socket_address))
1616  {
1617  GNUNET_break(0);
1618  GNUNET_free(plugin);
1619  return GNUNET_SYSERR;
1620  }
1621 
1622  GNUNET_free(plugin);
1623  switch (socket_address.ss_family)
1624  {
1625  case AF_INET: {
1626  struct IPv4TcpAddress *t4;
1627  struct sockaddr_in *in4 = (struct sockaddr_in *)&socket_address;
1628  t4 = GNUNET_new(struct IPv4TcpAddress);
1629  t4->options = htonl(options);
1630  t4->ipv4_addr = in4->sin_addr.s_addr;
1631  t4->t4_port = in4->sin_port;
1632  *buf = t4;
1633  *added = sizeof(struct IPv4TcpAddress);
1634  return GNUNET_OK;
1635  }
1636 
1637  case AF_INET6: {
1638  struct IPv6TcpAddress *t6;
1639  struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&socket_address;
1640  t6 = GNUNET_new(struct IPv6TcpAddress);
1641  t6->options = htonl(options);
1642  t6->ipv6_addr = in6->sin6_addr;
1643  t6->t6_port = in6->sin6_port;
1644  *buf = t6;
1645  *added = sizeof(struct IPv6TcpAddress);
1646  return GNUNET_OK;
1647  }
1648 
1649  default:
1650  return GNUNET_SYSERR;
1651  }
1652 }
1653 
1654 
1665 static struct GNUNET_ATS_Session *
1667  struct GNUNET_SERVER_Client *client)
1668 {
1670  struct GNUNET_ATS_Session);
1671 }
1672 
1673 
1683 static int
1685 {
1686  struct Plugin *plugin = cls;
1687  struct PendingMessage *pm;
1688 
1690  "Disconnecting session of peer `%s' address `%s'\n",
1691  GNUNET_i2s(&session->target),
1693  session->address->address,
1694  session->address->address_length));
1695 
1696  if (NULL != session->timeout_task)
1697  {
1699  session->timeout_task = NULL;
1701  }
1702 
1704  &session->target,
1705  session))
1706  {
1707  GNUNET_STATISTICS_update(session->plugin->env->stats,
1708  gettext_noop("# TCP sessions active"),
1709  -1,
1710  GNUNET_NO);
1711  }
1712  else
1713  {
1716  &session->target,
1717  session));
1718  }
1719  if (NULL != session->client)
1721 
1722  /* clean up state */
1723  if (NULL != session->transmit_handle)
1724  {
1726  session->transmit_handle = NULL;
1727  }
1728  session->plugin->env->session_end(session->plugin->env->cls,
1729  session->address,
1730  session);
1731 
1732  if (NULL != session->nat_connection_timeout)
1733  {
1735  session->nat_connection_timeout = NULL;
1736  }
1737 
1738  while (NULL != (pm = session->pending_messages_head))
1739  {
1741  (NULL != pm->transmit_cont)
1742  ? "Could not deliver message to `%s' at %s.\n"
1743  : "Could not deliver message to `%s' at %s, notifying.\n",
1744  GNUNET_i2s(&session->target),
1746  session->address->address,
1747  session->address->address_length));
1748  GNUNET_STATISTICS_update(session->plugin->env->stats,
1749  gettext_noop("# bytes currently in TCP buffers"),
1750  -(int64_t)pm->message_size,
1751  GNUNET_NO);
1752  GNUNET_STATISTICS_update(session->plugin->env->stats,
1753  gettext_noop(
1754  "# bytes discarded by TCP (disconnect)"),
1755  pm->message_size,
1756  GNUNET_NO);
1758  session->pending_messages_tail,
1759  pm);
1760  GNUNET_assert(0 < session->msgs_in_queue);
1761  session->msgs_in_queue--;
1762  GNUNET_assert(pm->message_size <= session->bytes_in_queue);
1763  session->bytes_in_queue -= pm->message_size;
1764  if (NULL != pm->transmit_cont)
1766  &session->target,
1767  GNUNET_SYSERR,
1768  pm->message_size,
1769  0);
1770  GNUNET_free(pm);
1771  }
1772  GNUNET_assert(0 == session->msgs_in_queue);
1773  GNUNET_assert(0 == session->bytes_in_queue);
1775 
1776  if (NULL != session->receive_delay_task)
1777  {
1779  session->receive_delay_task = NULL;
1780  }
1781  if (NULL != session->client)
1782  {
1784  session->client = NULL;
1785  }
1787  GNUNET_assert(NULL == session->transmit_handle);
1788  GNUNET_free(session);
1789  return GNUNET_OK;
1790 }
1791 
1792 
1801 static unsigned int
1803 {
1804  return 3;
1805 }
1806 
1807 
1813 static void
1815 {
1816  struct GNUNET_ATS_Session *s = cls;
1817  struct GNUNET_TIME_Relative left;
1818 
1819  s->timeout_task = NULL;
1821  if (0 != left.rel_value_us)
1822  {
1823  /* not actually our turn yet, but let's at least update
1824  the monitor, it may think we're about to die ... */
1827  return;
1828  }
1830  "Session %p was idle for %s, disconnecting\n",
1831  s,
1834  GNUNET_YES));
1835  /* call session destroy function */
1837 }
1838 
1839 
1845 static void
1847 {
1848  GNUNET_assert(NULL != s->timeout_task);
1849  s->timeout =
1851 }
1852 
1853 
1866 static struct GNUNET_ATS_Session *
1868  const struct GNUNET_HELLO_Address *address,
1870  struct GNUNET_SERVER_Client *client,
1871  int is_nat)
1872 {
1873  struct GNUNET_ATS_Session *session;
1874  struct PendingMessage *pm;
1875 
1876  if (GNUNET_YES != is_nat)
1877  GNUNET_assert(NULL != client);
1878  else
1879  GNUNET_assert(NULL == client);
1880 
1882  "Creating new session for peer `%s' at address %s\n",
1883  GNUNET_i2s(&address->peer),
1885  address->address,
1886  address->address_length));
1887  session = GNUNET_new(struct GNUNET_ATS_Session);
1889  session->plugin = plugin;
1890  session->is_nat = is_nat;
1891  if (NULL != client)
1892  {
1893  session->client = client;
1894  GNUNET_SERVER_client_set_user_context(client, session);
1895  }
1896  session->address = GNUNET_HELLO_address_copy(address);
1897  session->target = address->peer;
1898  session->expecting_welcome = GNUNET_YES;
1899  session->scope = scope;
1900  pm = GNUNET_malloc(sizeof(struct PendingMessage) +
1901  sizeof(struct WelcomeMessage));
1902  pm->msg = (const char *)&pm[1];
1903  pm->message_size = sizeof(struct WelcomeMessage);
1904  GNUNET_memcpy(&pm[1], &plugin->my_welcome, sizeof(struct WelcomeMessage));
1906  GNUNET_STATISTICS_update(plugin->env->stats,
1907  gettext_noop("# bytes currently in TCP buffers"),
1908  pm->message_size,
1909  GNUNET_NO);
1911  session->pending_messages_tail,
1912  pm);
1913  session->msgs_in_queue++;
1914  session->bytes_in_queue += pm->message_size;
1915  session->timeout =
1917  session->timeout_task =
1919  &session_timeout,
1920  session);
1922  if (GNUNET_YES != is_nat)
1923  {
1924  GNUNET_STATISTICS_update(plugin->env->stats,
1925  gettext_noop("# TCP sessions active"),
1926  1,
1927  GNUNET_NO);
1929  }
1930  else
1931  {
1932  notify_session_monitor(session->plugin,
1933  session,
1935  }
1936  return session;
1937 }
1938 
1939 
1946 static void
1948 
1949 
1961 static size_t
1962 do_transmit(void *cls, size_t size, void *buf)
1963 {
1964  struct GNUNET_ATS_Session *session = cls;
1965  struct GNUNET_PeerIdentity pid;
1966  struct Plugin *plugin;
1967  struct PendingMessage *pos;
1968  struct PendingMessage *hd;
1969  struct PendingMessage *tl;
1970  struct GNUNET_TIME_Absolute now;
1971  char *cbuf;
1972  size_t ret;
1973 
1974  session->transmit_handle = NULL;
1975  plugin = session->plugin;
1976  if (NULL == buf)
1977  {
1979  "Timeout trying to transmit to peer `%s', discarding message queue.\n",
1980  GNUNET_i2s(&session->target));
1981  /* timeout; cancel all messages that have already expired */
1982  hd = NULL;
1983  tl = NULL;
1984  ret = 0;
1985  now = GNUNET_TIME_absolute_get();
1986  while ((NULL != (pos = session->pending_messages_head)) &&
1987  (pos->timeout.abs_value_us <= now.abs_value_us))
1988  {
1990  session->pending_messages_tail,
1991  pos);
1992  GNUNET_assert(0 < session->msgs_in_queue);
1993  session->msgs_in_queue--;
1994  GNUNET_assert(pos->message_size <= session->bytes_in_queue);
1995  session->bytes_in_queue -= pos->message_size;
1997  "Failed to transmit %u byte message to `%s'.\n",
1998  pos->message_size,
1999  GNUNET_i2s(&session->target));
2000  ret += pos->message_size;
2001  GNUNET_CONTAINER_DLL_insert_after(hd, tl, tl, pos);
2002  }
2003  /* do this call before callbacks (so that if callbacks destroy
2004  * session, they have a chance to cancel actions done by this
2005  * call) */
2006  process_pending_messages(session);
2007  pid = session->target;
2008  /* no do callbacks and do not use session again since
2009  * the callbacks may abort the session */
2010  while (NULL != (pos = hd))
2011  {
2012  GNUNET_CONTAINER_DLL_remove(hd, tl, pos);
2013  if (NULL != pos->transmit_cont)
2014  pos->transmit_cont(pos->transmit_cont_cls,
2015  &pid,
2016  GNUNET_SYSERR,
2017  pos->message_size,
2018  0);
2019  GNUNET_free(pos);
2020  }
2021  GNUNET_STATISTICS_update(plugin->env->stats,
2022  gettext_noop("# bytes currently in TCP buffers"),
2023  -(int64_t)ret,
2024  GNUNET_NO);
2025  GNUNET_STATISTICS_update(plugin->env->stats,
2026  gettext_noop(
2027  "# bytes discarded by TCP (timeout)"),
2028  ret,
2029  GNUNET_NO);
2030  if (0 < ret)
2031  notify_session_monitor(session->plugin,
2032  session,
2034  return 0;
2035  }
2036  /* copy all pending messages that would fit */
2037  ret = 0;
2038  cbuf = buf;
2039  hd = NULL;
2040  tl = NULL;
2041  while (NULL != (pos = session->pending_messages_head))
2042  {
2043  if (ret + pos->message_size > size)
2044  break;
2046  session->pending_messages_tail,
2047  pos);
2048  GNUNET_assert(0 < session->msgs_in_queue);
2049  session->msgs_in_queue--;
2050  GNUNET_assert(pos->message_size <= session->bytes_in_queue);
2051  session->bytes_in_queue -= pos->message_size;
2052  GNUNET_assert(size >= pos->message_size);
2054  "Transmitting message of type %u size %u to peer %s at %s\n",
2055  ntohs(((struct GNUNET_MessageHeader *)pos->msg)->type),
2056  pos->message_size,
2057  GNUNET_i2s(&session->target),
2059  session->address->address,
2060  session->address->address_length));
2061  /* FIXME: this GNUNET_memcpy can be up to 7% of our total runtime */
2062  GNUNET_memcpy(cbuf, pos->msg, pos->message_size);
2063  cbuf += pos->message_size;
2064  ret += pos->message_size;
2065  size -= pos->message_size;
2066  GNUNET_CONTAINER_DLL_insert_tail(hd, tl, pos);
2067  }
2069  /* schedule 'continuation' before callbacks so that callbacks that
2070  * cancel everything don't cause us to use a session that no longer
2071  * exists... */
2072  process_pending_messages(session);
2074  pid = session->target;
2075  /* we'll now call callbacks that may cancel the session; hence
2076  * we should not use 'session' after this point */
2077  while (NULL != (pos = hd))
2078  {
2079  GNUNET_CONTAINER_DLL_remove(hd, tl, pos);
2080  if (NULL != pos->transmit_cont)
2081  pos->transmit_cont(pos->transmit_cont_cls,
2082  &pid,
2083  GNUNET_OK,
2084  pos->message_size,
2085  pos->message_size); /* FIXME: include TCP overhead */
2086  GNUNET_free(pos);
2087  }
2088  GNUNET_assert(NULL == hd);
2089  GNUNET_assert(NULL == tl);
2090  GNUNET_STATISTICS_update(plugin->env->stats,
2091  gettext_noop("# bytes currently in TCP buffers"),
2092  -(int64_t)ret,
2093  GNUNET_NO);
2094  GNUNET_STATISTICS_update(plugin->env->stats,
2095  gettext_noop("# bytes transmitted via TCP"),
2096  ret,
2097  GNUNET_NO);
2098  return ret;
2099 }
2100 
2101 
2108 static void
2110 {
2111  struct PendingMessage *pm;
2112 
2113  GNUNET_assert(NULL != session->client);
2114  if (NULL != session->transmit_handle)
2115  return;
2116  if (NULL == (pm = session->pending_messages_head))
2117  return;
2118 
2119  session->transmit_handle =
2121  pm->message_size,
2123  pm->timeout),
2124  &do_transmit,
2125  session);
2126 }
2127 
2128 
2156 static ssize_t
2158  struct GNUNET_ATS_Session *session,
2159  const char *msgbuf,
2160  size_t msgbuf_size,
2161  unsigned int priority,
2162  struct GNUNET_TIME_Relative to,
2164  void *cont_cls)
2165 {
2166  struct Plugin *plugin = cls;
2167  struct PendingMessage *pm;
2168 
2169  /* create new message entry */
2170  pm = GNUNET_malloc(sizeof(struct PendingMessage) + msgbuf_size);
2171  pm->msg = (const char *)&pm[1];
2172  GNUNET_memcpy(&pm[1], msgbuf, msgbuf_size);
2173  pm->message_size = msgbuf_size;
2175  pm->transmit_cont = cont;
2176  pm->transmit_cont_cls = cont_cls;
2177 
2179  "Asked to transmit %u bytes to `%s', added message to list.\n",
2180  msgbuf_size,
2181  GNUNET_i2s(&session->target));
2182 
2183  if (GNUNET_YES ==
2185  &session->target,
2186  session))
2187  {
2188  GNUNET_assert(NULL != session->client);
2191  GNUNET_STATISTICS_update(plugin->env->stats,
2192  gettext_noop("# bytes currently in TCP buffers"),
2193  msgbuf_size,
2194  GNUNET_NO);
2195 
2196  /* append pm to pending_messages list */
2198  session->pending_messages_tail,
2199  pm);
2200  notify_session_monitor(session->plugin,
2201  session,
2203  session->msgs_in_queue++;
2204  session->bytes_in_queue += pm->message_size;
2205  process_pending_messages(session);
2206  return msgbuf_size;
2207  }
2208  if (GNUNET_YES ==
2210  &session->target,
2211  session))
2212  {
2214  "This NAT WAIT session for peer `%s' is not yet ready!\n",
2215  GNUNET_i2s(&session->target));
2216  GNUNET_STATISTICS_update(plugin->env->stats,
2217  gettext_noop("# bytes currently in TCP buffers"),
2218  msgbuf_size,
2219  GNUNET_NO);
2220  /* append pm to pending_messages list */
2222  session->pending_messages_tail,
2223  pm);
2224  session->msgs_in_queue++;
2225  session->bytes_in_queue += pm->message_size;
2226  notify_session_monitor(session->plugin,
2227  session,
2229  return msgbuf_size;
2230  }
2231  LOG(GNUNET_ERROR_TYPE_ERROR, "Invalid session %p\n", session);
2232  if (NULL != cont)
2233  cont(cont_cls, &session->target, GNUNET_SYSERR, pm->message_size, 0);
2234  GNUNET_break(0);
2235  GNUNET_free(pm);
2236  return GNUNET_SYSERR; /* session does not exist here */
2237 }
2238 
2239 
2248 
2253 };
2254 
2255 
2264 static int
2266  const struct GNUNET_PeerIdentity *key,
2267  void *value)
2268 {
2269  struct GNUNET_ATS_SessionItCtx *si_ctx = cls;
2270  struct GNUNET_ATS_Session *session = value;
2271 
2272  if (0 != GNUNET_HELLO_address_cmp(si_ctx->address, session->address))
2273  return GNUNET_YES;
2274  si_ctx->result = session;
2275  return GNUNET_NO;
2276 }
2277 
2278 
2284 static void
2286 {
2287  struct GNUNET_ATS_Session *session = cls;
2288 
2289  session->nat_connection_timeout = NULL;
2291  "NAT WAIT connection to `%4s' at `%s' could not be established, removing session\n",
2292  GNUNET_i2s(&session->target),
2294  session->address->address,
2295  session->address->address_length));
2296  tcp_plugin_disconnect_session(session->plugin, session);
2297 }
2298 
2299 
2309 static void
2311  const struct GNUNET_PeerIdentity *peer,
2312  struct GNUNET_ATS_Session *session)
2313 {
2314  reschedule_session_timeout(session);
2315 }
2316 
2317 
2324 static void
2325 delayed_done(void *cls)
2326 {
2327  struct GNUNET_ATS_Session *session = cls;
2328 
2329  session->receive_delay_task = NULL;
2330  reschedule_session_timeout(session);
2332 }
2333 
2334 
2345 static void
2347  const struct GNUNET_PeerIdentity *peer,
2348  struct GNUNET_ATS_Session *session,
2349  struct GNUNET_TIME_Relative delay)
2350 {
2351  if (NULL == session->receive_delay_task)
2352  return;
2354  "New inbound delay %s\n",
2358  session->receive_delay_task =
2359  GNUNET_SCHEDULER_add_delayed(delay, &delayed_done, session);
2360 }
2361 
2362 
2372 static struct GNUNET_ATS_Session *
2374 {
2375  struct Plugin *plugin = cls;
2376  struct GNUNET_ATS_Session *session = NULL;
2377  int af;
2378  const void *sb;
2379  size_t sbs;
2380  struct GNUNET_CONNECTION_Handle *sa;
2381  struct sockaddr_in a4;
2382  struct sockaddr_in6 a6;
2383  const struct IPv4TcpAddress *t4;
2384  const struct IPv6TcpAddress *t6;
2385  unsigned int options;
2386  enum GNUNET_NetworkType net_type;
2387  unsigned int is_natd = GNUNET_NO;
2388  size_t addrlen;
2389 
2390 #ifdef TCP_STEALTH
2391  struct GNUNET_NETWORK_Handle *s;
2392 #endif
2393 
2394  addrlen = address->address_length;
2396  "Trying to get session for `%s' address of peer `%s'\n",
2398  address->address,
2399  address->address_length),
2400  GNUNET_i2s(&address->peer));
2401 
2404  {
2405  GNUNET_break(0);
2406  return NULL;
2407  }
2408 
2409  /* look for existing session */
2411  &address->peer))
2412  {
2413  struct GNUNET_ATS_SessionItCtx si_ctx;
2414 
2415  si_ctx.address = address;
2416  si_ctx.result = NULL;
2418  &address->peer,
2420  &si_ctx);
2421  if (NULL != si_ctx.result)
2422  {
2423  session = si_ctx.result;
2425  "Found existing session for `%s' address `%s'\n",
2426  GNUNET_i2s(&address->peer),
2428  address->address,
2429  address->address_length));
2430  return session;
2431  }
2432  /* This is a bit of a hack, limiting TCP to never allow more than
2433  one TCP connection to any given peer at the same time.
2434  Without this, peers sometimes disagree about which of the TCP
2435  connections they should use, causing one side to believe that
2436  they transmit successfully, while the other receives nothing. */
2437  return NULL; /* Refuse to have more than one TCP connection per
2438  peer pair at the same time. */
2439  }
2440 
2441  if (addrlen == sizeof(struct IPv6TcpAddress))
2442  {
2443  GNUNET_assert(NULL != address->address); /* make static analysis happy */
2444  t6 = address->address;
2445  options = t6->options;
2446  af = AF_INET6;
2447  memset(&a6, 0, sizeof(a6));
2448 #if HAVE_SOCKADDR_IN_SIN_LEN
2449  a6.sin6_len = sizeof(a6);
2450 #endif
2451  a6.sin6_family = AF_INET6;
2452  a6.sin6_port = t6->t6_port;
2453  if (t6->t6_port == 0)
2454  is_natd = GNUNET_YES;
2455  GNUNET_memcpy(&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
2456  sb = &a6;
2457  sbs = sizeof(a6);
2458  }
2459  else if (addrlen == sizeof(struct IPv4TcpAddress))
2460  {
2461  GNUNET_assert(NULL != address->address); /* make static analysis happy */
2462  t4 = address->address;
2463  options = t4->options;
2464  af = AF_INET;
2465  memset(&a4, 0, sizeof(a4));
2466 #if HAVE_SOCKADDR_IN_SIN_LEN
2467  a4.sin_len = sizeof(a4);
2468 #endif
2469  a4.sin_family = AF_INET;
2470  a4.sin_port = t4->t4_port;
2471  if (t4->t4_port == 0)
2472  is_natd = GNUNET_YES;
2473  a4.sin_addr.s_addr = t4->ipv4_addr;
2474  sb = &a4;
2475  sbs = sizeof(a4);
2476  }
2477  else
2478  {
2480  plugin->env->stats,
2481  gettext_noop("# requests to create session with invalid address"),
2482  1,
2483  GNUNET_NO);
2484  return NULL;
2485  }
2486 
2487  net_type = plugin->env->get_address_type(plugin->env->cls, sb, sbs);
2488  GNUNET_break(net_type != GNUNET_NT_UNSPECIFIED);
2489 
2490  if ((is_natd == GNUNET_YES) && (addrlen == sizeof(struct IPv6TcpAddress)))
2491  {
2492  /* NAT client only works with IPv4 addresses */
2493  return NULL;
2494  }
2495 
2496  if (plugin->cur_connections >= plugin->max_connections)
2497  {
2498  /* saturated */
2499  return NULL;
2500  }
2501 
2502  if ((is_natd == GNUNET_YES) &&
2503  (GNUNET_YES ==
2505  &address->peer)))
2506  {
2507  /* Only do one NAT punch attempt per peer identity */
2508  return NULL;
2509  }
2510 
2511  if ((is_natd == GNUNET_YES) && (NULL != plugin->nat) &&
2512  (GNUNET_NO ==
2514  &address->peer)))
2515  {
2516  struct sockaddr_in local_sa;
2517 
2519  "Found valid IPv4 NAT address (creating session)!\n");
2520  session = create_session(plugin, address, net_type, NULL, GNUNET_YES);
2521  session->nat_connection_timeout =
2525  plugin->nat_wait_conns,
2526  &session->target,
2527  session,
2529 
2531  "Created NAT WAIT connection to `%s' at `%s'\n",
2532  GNUNET_i2s(&session->target),
2533  GNUNET_a2s(sb, sbs));
2534  memset(&local_sa, 0, sizeof(local_sa));
2535  local_sa.sin_family = AF_INET;
2536  local_sa.sin_port = htons(plugin->open_port);
2537  /* We leave sin_address at 0, let the kernel figure it out,
2538  even if our bind() is more specific. (May want to reconsider
2539  later.) */
2540  if (GNUNET_OK == GNUNET_NAT_request_reversal(plugin->nat, &local_sa, &a4))
2541  return session;
2543  "Running NAT client for `%s' at `%s' failed\n",
2544  GNUNET_i2s(&session->target),
2545  GNUNET_a2s(sb, sbs));
2546  tcp_plugin_disconnect_session(plugin, session);
2547  return NULL;
2548  }
2549 
2550  /* create new outbound session */
2551  if (0 != (options & TCP_OPTIONS_TCP_STEALTH))
2552  {
2553 #ifdef TCP_STEALTH
2554  s = GNUNET_NETWORK_socket_create(af, SOCK_STREAM, 0);
2555  if (NULL == s)
2556  {
2558  "socket");
2559  sa = NULL;
2560  }
2561  else
2562  {
2563  if ((GNUNET_OK !=
2565  IPPROTO_TCP,
2566  TCP_STEALTH,
2567  &session->target,
2568  sizeof(
2569  struct GNUNET_PeerIdentity))) ||
2570  (GNUNET_OK !=
2572  IPPROTO_TCP,
2573  TCP_STEALTH_INTEGRITY,
2574  &plugin->my_welcome,
2575  sizeof(struct WelcomeMessage))))
2576  {
2577  /* TCP STEALTH not supported by kernel */
2579  sa = NULL;
2580  }
2581  else
2582  {
2583  sa = GNUNET_CONNECTION_connect_socket(s, sb, sbs);
2584  }
2585  }
2586 #else
2587  sa = NULL;
2588 #endif
2589  }
2590  else
2591  {
2592  sa = GNUNET_CONNECTION_create_from_sockaddr(af, sb, sbs);
2593  }
2594  if (NULL == sa)
2595  {
2597  "Failed to create connection to `%s' at `%s'\n",
2598  GNUNET_i2s(&address->peer),
2599  GNUNET_a2s(sb, sbs));
2600  return NULL;
2601  }
2603  "Asked to transmit to `%s', creating fresh session using address `%s'.\n",
2604  GNUNET_i2s(&address->peer),
2605  GNUNET_a2s(sb, sbs));
2606 
2607  session = create_session(plugin,
2608  address,
2609  net_type,
2610  GNUNET_SERVER_connect_socket(plugin->server, sa),
2611  GNUNET_NO);
2613  plugin->sessionmap,
2614  &session->target,
2615  session,
2617  /* Send TCP Welcome */
2618  process_pending_messages(session);
2619 
2620  return session;
2621 }
2622 
2623 
2634 static int
2636  const struct GNUNET_PeerIdentity *key,
2637  void *value)
2638 {
2639  struct Plugin *plugin = cls;
2640  struct GNUNET_ATS_Session *session = value;
2641 
2642  GNUNET_STATISTICS_update(session->plugin->env->stats,
2643  gettext_noop(
2644  "# transport-service disconnect requests for TCP"),
2645  1,
2646  GNUNET_NO);
2647  tcp_plugin_disconnect_session(plugin, session);
2648  return GNUNET_YES;
2649 }
2650 
2651 
2668 static void
2670 {
2671  struct Plugin *plugin = cls;
2672 
2674  "Disconnecting peer `%s'\n",
2675  GNUNET_i2s(target));
2677  target,
2679  plugin);
2681  target,
2683  plugin);
2684 }
2685 
2686 
2697 static void
2698 append_port(void *cls, const char *hostname)
2699 {
2700  struct PrettyPrinterContext *ppc = cls;
2701  struct Plugin *plugin = ppc->plugin;
2702  char *ret;
2703 
2705  "append_port called with hostname `%s'\n",
2706  hostname);
2707  if (NULL == hostname)
2708  {
2709  /* Final call, done */
2710  ppc->resolver_handle = NULL;
2712  plugin->ppc_dll_tail,
2713  ppc);
2714  ppc->asc(ppc->asc_cls, NULL, GNUNET_OK);
2715  GNUNET_free(ppc);
2716  return;
2717  }
2718  if (GNUNET_YES == ppc->ipv6)
2719  GNUNET_asprintf(&ret,
2720  "%s.%u.[%s]:%d",
2721  PLUGIN_NAME,
2722  ppc->options,
2723  hostname,
2724  ppc->port);
2725  else
2726  GNUNET_asprintf(&ret,
2727  "%s.%u.%s:%d",
2728  PLUGIN_NAME,
2729  ppc->options,
2730  hostname,
2731  ppc->port);
2732  ppc->asc(ppc->asc_cls, ret, GNUNET_OK);
2733  GNUNET_free(ret);
2734 }
2735 
2736 
2750 static void
2752  const char *type,
2753  const void *addr,
2754  size_t addrlen,
2755  int numeric,
2758  void *asc_cls)
2759 {
2760  struct Plugin *plugin = cls;
2761  struct PrettyPrinterContext *ppc;
2762  const void *sb;
2763  size_t sbs;
2764  struct sockaddr_in a4;
2765  struct sockaddr_in6 a6;
2766  const struct IPv4TcpAddress *t4;
2767  const struct IPv6TcpAddress *t6;
2768  uint16_t port;
2769  uint32_t options;
2770 
2771  if (sizeof(struct IPv6TcpAddress) == addrlen)
2772  {
2773  t6 = addr;
2774  memset(&a6, 0, sizeof(a6));
2775  a6.sin6_family = AF_INET6;
2776  a6.sin6_port = t6->t6_port;
2777  GNUNET_memcpy(&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
2778  port = ntohs(t6->t6_port);
2779  options = ntohl(t6->options);
2780  sb = &a6;
2781  sbs = sizeof(a6);
2782  }
2783  else if (sizeof(struct IPv4TcpAddress) == addrlen)
2784  {
2785  t4 = addr;
2786  memset(&a4, 0, sizeof(a4));
2787  a4.sin_family = AF_INET;
2788  a4.sin_port = t4->t4_port;
2789  a4.sin_addr.s_addr = t4->ipv4_addr;
2790  port = ntohs(t4->t4_port);
2791  options = ntohl(t4->options);
2792  sb = &a4;
2793  sbs = sizeof(a4);
2794  }
2795  else
2796  {
2797  /* invalid address */
2799  _("Unexpected address length: %u bytes\n"),
2800  (unsigned int)addrlen);
2801  asc(asc_cls, NULL, GNUNET_SYSERR);
2802  asc(asc_cls, NULL, GNUNET_OK);
2803  return;
2804  }
2805  ppc = GNUNET_new(struct PrettyPrinterContext);
2806  ppc->plugin = plugin;
2807  if (addrlen == sizeof(struct IPv6TcpAddress))
2808  ppc->ipv6 = GNUNET_YES;
2809  else
2810  ppc->ipv6 = GNUNET_NO;
2811  ppc->asc = asc;
2812  ppc->asc_cls = asc_cls;
2813  ppc->port = port;
2814  ppc->options = options;
2815  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Starting DNS reverse lookup\n");
2817  sbs,
2818  !numeric,
2819  timeout,
2820  &append_port,
2821  ppc);
2822  if (NULL == ppc->resolver_handle)
2823  {
2824  GNUNET_break(0);
2825  GNUNET_free(ppc);
2826  return;
2827  }
2828  GNUNET_CONTAINER_DLL_insert(plugin->ppc_dll_head, plugin->ppc_dll_tail, ppc);
2829 }
2830 
2831 
2847 static int
2848 tcp_plugin_check_address(void *cls, const void *addr, size_t addrlen)
2849 {
2850  struct Plugin *plugin = cls;
2851  const struct IPv4TcpAddress *v4;
2852  const struct IPv6TcpAddress *v6;
2853 
2854  if ((addrlen != sizeof(struct IPv4TcpAddress)) &&
2855  (addrlen != sizeof(struct IPv6TcpAddress)))
2856  {
2857  GNUNET_break_op(0);
2858  return GNUNET_SYSERR;
2859  }
2860 
2861  if (addrlen == sizeof(struct IPv4TcpAddress))
2862  {
2863  struct sockaddr_in s4;
2864 
2865  v4 = (const struct IPv4TcpAddress *)addr;
2866  if (0 != memcmp(&v4->options, &plugin->myoptions, sizeof(uint32_t)))
2867  {
2868  GNUNET_break(0);
2869  return GNUNET_SYSERR;
2870  }
2871  memset(&s4, 0, sizeof(s4));
2872  s4.sin_family = AF_INET;
2873 #if HAVE_SOCKADDR_IN_SIN_LEN
2874  s4.sin_len = sizeof(s4);
2875 #endif
2876  s4.sin_port = v4->t4_port;
2877  s4.sin_addr.s_addr = v4->ipv4_addr;
2878 
2879  if (GNUNET_OK !=
2880  GNUNET_NAT_test_address(plugin->nat, &s4, sizeof(struct sockaddr_in)))
2881  return GNUNET_SYSERR;
2882  }
2883  else
2884  {
2885  struct sockaddr_in6 s6;
2886 
2887  v6 = (const struct IPv6TcpAddress *)addr;
2888  if (IN6_IS_ADDR_LINKLOCAL(&v6->ipv6_addr))
2889  {
2890  GNUNET_break_op(0);
2891  return GNUNET_SYSERR;
2892  }
2893  if (0 != memcmp(&v6->options, &plugin->myoptions, sizeof(uint32_t)))
2894  {
2895  GNUNET_break(0);
2896  return GNUNET_SYSERR;
2897  }
2898  memset(&s6, 0, sizeof(s6));
2899  s6.sin6_family = AF_INET6;
2900 #if HAVE_SOCKADDR_IN_SIN_LEN
2901  s6.sin6_len = sizeof(s6);
2902 #endif
2903  s6.sin6_port = v6->t6_port;
2904  s6.sin6_addr = v6->ipv6_addr;
2905 
2906  if (GNUNET_OK != GNUNET_NAT_test_address(plugin->nat,
2907  &s6,
2908  sizeof(struct sockaddr_in6)))
2909  return GNUNET_SYSERR;
2910  }
2911  return GNUNET_OK;
2912 }
2913 
2914 
2924 static void
2926  struct GNUNET_SERVER_Client *client,
2927  const struct GNUNET_MessageHeader *message)
2928 {
2929  struct Plugin *plugin = cls;
2930  struct GNUNET_ATS_Session *session;
2931  const struct TCP_NAT_ProbeMessage *tcp_nat_probe;
2932  size_t alen;
2933  void *vaddr;
2934  struct IPv4TcpAddress *t4;
2935  struct IPv6TcpAddress *t6;
2936  const struct sockaddr_in *s4;
2937  const struct sockaddr_in6 *s6;
2938 
2939  LOG(GNUNET_ERROR_TYPE_DEBUG, "Received NAT probe\n");
2940  /* We have received a TCP NAT probe, meaning we (hopefully) initiated
2941  * a connection to this peer by running gnunet-nat-client. This peer
2942  * received the punch message and now wants us to use the new connection
2943  * as the default for that peer. Do so and then send a WELCOME message
2944  * so we can really be connected!
2945  */
2946  if (ntohs(message->size) != sizeof(struct TCP_NAT_ProbeMessage))
2947  {
2948  GNUNET_break_op(0);
2950  return;
2951  }
2952 
2953  tcp_nat_probe = (const struct TCP_NAT_ProbeMessage *)message;
2954  if (0 == memcmp(&tcp_nat_probe->clientIdentity,
2955  plugin->env->my_identity,
2956  sizeof(struct GNUNET_PeerIdentity)))
2957  {
2958  /* refuse connections from ourselves */
2960  return;
2961  }
2962 
2964  &tcp_nat_probe->clientIdentity);
2965  if (NULL == session)
2966  {
2967  LOG(GNUNET_ERROR_TYPE_DEBUG, "Did NOT find session for NAT probe!\n");
2969  return;
2970  }
2971  LOG(GNUNET_ERROR_TYPE_DEBUG, "Found session for NAT probe!\n");
2972 
2973  if (NULL != session->nat_connection_timeout)
2974  {
2976  session->nat_connection_timeout = NULL;
2977  }
2978 
2979  if (GNUNET_OK != GNUNET_SERVER_client_get_address(client, &vaddr, &alen))
2980  {
2981  GNUNET_break(0);
2983  tcp_plugin_disconnect_session(plugin, session);
2984  return;
2985  }
2986  GNUNET_assert(
2987  GNUNET_YES ==
2989  &tcp_nat_probe->clientIdentity,
2990  session));
2991  GNUNET_SERVER_client_set_user_context(client, session);
2993  plugin->sessionmap,
2994  &session->target,
2995  session,
2999  "Found address `%s' for incoming connection\n",
3000  GNUNET_a2s(vaddr, alen));
3001  switch (((const struct sockaddr *)vaddr)->sa_family)
3002  {
3003  case AF_INET:
3004  s4 = vaddr;
3005  t4 = GNUNET_new(struct IPv4TcpAddress);
3006  t4->options = htonl(TCP_OPTIONS_NONE);
3007  t4->t4_port = s4->sin_port;
3008  t4->ipv4_addr = s4->sin_addr.s_addr;
3009  session->address =
3011  PLUGIN_NAME,
3012  &t4,
3013  sizeof(struct IPv4TcpAddress),
3015  break;
3016 
3017  case AF_INET6:
3018  s6 = vaddr;
3019  t6 = GNUNET_new(struct IPv6TcpAddress);
3020  t6->options = htonl(TCP_OPTIONS_NONE);
3021  t6->t6_port = s6->sin6_port;
3022  GNUNET_memcpy(&t6->ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
3023  session->address =
3025  PLUGIN_NAME,
3026  &t6,
3027  sizeof(struct IPv6TcpAddress),
3029  break;
3030 
3031  default:
3032  GNUNET_break_op(0);
3033  LOG(GNUNET_ERROR_TYPE_DEBUG, "Bad address for incoming connection!\n");
3034  GNUNET_free(vaddr);
3036  tcp_plugin_disconnect_session(plugin, session);
3037  return;
3038  }
3039  GNUNET_free(vaddr);
3040  GNUNET_break(NULL == session->client);
3041  session->client = client;
3042  GNUNET_STATISTICS_update(plugin->env->stats,
3043  gettext_noop("# TCP sessions active"),
3044  1,
3045  GNUNET_NO);
3046  process_pending_messages(session);
3048 }
3049 
3050 
3059 static void
3061  struct GNUNET_SERVER_Client *client,
3062  const struct GNUNET_MessageHeader *message)
3063 {
3064  struct Plugin *plugin = cls;
3065  const struct WelcomeMessage *wm = (const struct WelcomeMessage *)message;
3066  struct GNUNET_HELLO_Address *address;
3067  struct GNUNET_ATS_Session *session;
3068  size_t alen;
3069  void *vaddr;
3070  struct IPv4TcpAddress t4;
3071  struct IPv6TcpAddress t6;
3072  const struct sockaddr_in *s4;
3073  const struct sockaddr_in6 *s6;
3074 
3075  if (0 == memcmp(&wm->clientIdentity,
3076  plugin->env->my_identity,
3077  sizeof(struct GNUNET_PeerIdentity)))
3078  {
3079  /* refuse connections from ourselves */
3080  if (GNUNET_OK == GNUNET_SERVER_client_get_address(client, &vaddr, &alen))
3081  {
3083  "Received WELCOME message from my own identity `%s' on address `%s'\n",
3084  GNUNET_i2s(&wm->clientIdentity),
3085  GNUNET_a2s(vaddr, alen));
3086  GNUNET_free(vaddr);
3087  }
3089  return;
3090  }
3091 
3092  if (GNUNET_OK == GNUNET_SERVER_client_get_address(client, &vaddr, &alen))
3093  {
3095  "Received WELCOME message from `%s' on address `%s'\n",
3096  GNUNET_i2s(&wm->clientIdentity),
3097  GNUNET_a2s(vaddr, alen));
3098  GNUNET_free(vaddr);
3099  }
3100  GNUNET_STATISTICS_update(plugin->env->stats,
3101  gettext_noop("# TCP WELCOME messages received"),
3102  1,
3103  GNUNET_NO);
3104  session = lookup_session_by_client(plugin, client);
3105  if (NULL != session)
3106  {
3107  if (GNUNET_OK == GNUNET_SERVER_client_get_address(client, &vaddr, &alen))
3108  {
3110  "Found existing session %p for peer `%s'\n",
3111  session,
3112  GNUNET_a2s(vaddr, alen));
3113  GNUNET_free(vaddr);
3114  }
3115  }
3116  else
3117  {
3118  if (GNUNET_OK == GNUNET_SERVER_client_get_address(client, &vaddr, &alen))
3119  {
3120  if (alen == sizeof(struct sockaddr_in))
3121  {
3122  s4 = vaddr;
3123  memset(&t4, '\0', sizeof(t4));
3124  t4.options = htonl(TCP_OPTIONS_NONE);
3125  t4.t4_port = s4->sin_port;
3126  t4.ipv4_addr = s4->sin_addr.s_addr;
3127  address =
3129  PLUGIN_NAME,
3130  &t4,
3131  sizeof(t4),
3133  }
3134  else if (alen == sizeof(struct sockaddr_in6))
3135  {
3136  s6 = vaddr;
3137  memset(&t6, '\0', sizeof(t6));
3138  t6.options = htonl(TCP_OPTIONS_NONE);
3139  t6.t6_port = s6->sin6_port;
3140  GNUNET_memcpy(&t6.ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
3141  address =
3143  PLUGIN_NAME,
3144  &t6,
3145  sizeof(t6),
3147  }
3148  else
3149  {
3150  GNUNET_break(0);
3151  GNUNET_free_non_null(vaddr);
3153  return;
3154  }
3155  session = create_session(plugin,
3156  address,
3157  plugin->env->get_address_type(plugin->env->cls,
3158  vaddr,
3159  alen),
3160  client,
3161  GNUNET_NO);
3163  GNUNET_HELLO_address_free(address);
3165  "Creating new%s session %p for peer `%s' client %p\n",
3168  ? " inbound"
3169  : "",
3170  session,
3172  session->address->address,
3173  session->address->address_length),
3174  client);
3175  GNUNET_free(vaddr);
3177  plugin->sessionmap,
3178  &session->target,
3179  session,
3181  /* Notify transport and ATS about new session */
3182  plugin->env->session_start(plugin->env->cls,
3183  session->address,
3184  session,
3185  session->scope);
3186  }
3187  else
3188  {
3190  "Did not obtain TCP socket address for incoming connection\n");
3191  GNUNET_break(0);
3193  return;
3194  }
3195  }
3196 
3197  if (GNUNET_YES != session->expecting_welcome)
3198  {
3199  GNUNET_break_op(0);
3201  return;
3202  }
3204  session->expecting_welcome = GNUNET_NO;
3205 
3206  process_pending_messages(session);
3210 }
3211 
3212 
3221 static void
3223  struct GNUNET_SERVER_Client *client,
3224  const struct GNUNET_MessageHeader *message)
3225 {
3226  struct Plugin *plugin = cls;
3227  struct GNUNET_ATS_Session *session;
3228  struct GNUNET_TIME_Relative delay;
3229  uint16_t type;
3230 
3231  type = ntohs(message->type);
3234  {
3235  /* We don't want to propagate WELCOME and NAT Probe messages up! */
3237  return;
3238  }
3239  session = lookup_session_by_client(plugin, client);
3240  if (NULL == session)
3241  {
3242  /* No inbound session found */
3243  void *vaddr = NULL;
3244  size_t alen;
3245 
3247  GNUNET_SERVER_client_get_address(client, &vaddr, &alen));
3249  "Received unexpected %u bytes of type %u from `%s'\n",
3250  (unsigned int)ntohs(message->size),
3251  (unsigned int)ntohs(message->type),
3252  GNUNET_a2s(vaddr, alen));
3253  GNUNET_break_op(0);
3255  GNUNET_free_non_null(vaddr);
3256  return;
3257  }
3258  if (GNUNET_YES == session->expecting_welcome)
3259  {
3260  /* Session is expecting WELCOME message */
3261  void *vaddr = NULL;
3262  size_t alen;
3263 
3264  GNUNET_SERVER_client_get_address(client, &vaddr, &alen);
3266  "Received unexpected %u bytes of type %u from `%s'\n",
3267  (unsigned int)ntohs(message->size),
3268  (unsigned int)ntohs(message->type),
3269  GNUNET_a2s(vaddr, alen));
3270  GNUNET_break_op(0);
3272  GNUNET_free_non_null(vaddr);
3273  return;
3274  }
3275 
3277  {
3278  void *vaddr = NULL;
3279  size_t alen;
3280 
3281  GNUNET_SERVER_client_get_address(client, &vaddr, &alen);
3283  "Passing %u bytes of type %u from `%s' at %s to transport service.\n",
3284  (unsigned int)ntohs(message->size),
3285  (unsigned int)ntohs(message->type),
3286  GNUNET_i2s(&session->target),
3287  GNUNET_a2s(vaddr, alen));
3288  GNUNET_free_non_null(vaddr);
3289  }
3290 
3291  GNUNET_STATISTICS_update(plugin->env->stats,
3292  gettext_noop("# bytes received via TCP"),
3293  ntohs(message->size),
3294  GNUNET_NO);
3295 
3296  GNUNET_assert(
3298  &session->target,
3299  session));
3300  delay =
3301  plugin->env->receive(plugin->env->cls, session->address, session, message);
3302  reschedule_session_timeout(session);
3303  if (0 == delay.rel_value_us)
3304  {
3306  }
3307  else
3308  {
3310  "Throttling receiving from `%s' for %s\n",
3311  GNUNET_i2s(&session->target),
3314  GNUNET_assert(NULL == session->receive_delay_task);
3315  session->receive_delay_task =
3316  GNUNET_SCHEDULER_add_delayed(delay, &delayed_done, session);
3317  }
3318 }
3319 
3320 
3329 static void
3330 connect_notify(void *cls, struct GNUNET_SERVER_Client *client)
3331 {
3332  struct Plugin *plugin = cls;
3333 
3334  if (NULL == client)
3335  return;
3336  plugin->cur_connections++;
3337  GNUNET_STATISTICS_set(plugin->env->stats,
3338  gettext_noop("# TCP server connections active"),
3339  plugin->cur_connections,
3340  GNUNET_NO);
3341  GNUNET_STATISTICS_update(plugin->env->stats,
3342  gettext_noop("# TCP server connect events"),
3343  1,
3344  GNUNET_NO);
3345  if (plugin->cur_connections != plugin->max_connections)
3346  return;
3348  _("TCP connection limit reached, suspending server\n"));
3349  GNUNET_STATISTICS_update(plugin->env->stats,
3350  gettext_noop("# TCP service suspended"),
3351  1,
3352  GNUNET_NO);
3354  plugin->server); /* Maximum number of connections rechead */
3355 }
3356 
3357 
3366 static void
3367 disconnect_notify(void *cls, struct GNUNET_SERVER_Client *client)
3368 {
3369  struct Plugin *plugin = cls;
3370  struct GNUNET_ATS_Session *session;
3371 
3372  if (NULL == client)
3373  return;
3374  GNUNET_assert(plugin->cur_connections >= 1);
3375  plugin->cur_connections--;
3376  session = lookup_session_by_client(plugin, client);
3377  if (NULL == session)
3378  return; /* unknown, nothing to do */
3380  "Destroying session of `%s' with %s due to network-level disconnect.\n",
3381  GNUNET_i2s(&session->target),
3383  session->address->address,
3384  session->address->address_length));
3385 
3386  if (plugin->cur_connections == plugin->max_connections)
3387  {
3388  GNUNET_STATISTICS_update(session->plugin->env->stats,
3389  gettext_noop("# TCP service resumed"),
3390  1,
3391  GNUNET_NO);
3392  GNUNET_SERVER_resume(plugin->server); /* Resume server */
3393  }
3394  GNUNET_STATISTICS_set(plugin->env->stats,
3395  gettext_noop("# TCP server connections active"),
3396  plugin->cur_connections,
3397  GNUNET_NO);
3398  GNUNET_STATISTICS_update(session->plugin->env->stats,
3399  gettext_noop(
3400  "# network-level TCP disconnect events"),
3401  1,
3402  GNUNET_NO);
3403  tcp_plugin_disconnect_session(plugin, session);
3404 }
3405 
3406 
3415 static size_t
3416 notify_send_probe(void *cls, size_t size, void *buf)
3417 {
3418  struct TCPProbeContext *tcp_probe_ctx = cls;
3419  struct Plugin *plugin = tcp_probe_ctx->plugin;
3420  size_t ret;
3421 
3422  tcp_probe_ctx->transmit_handle = NULL;
3424  plugin->probe_tail,
3425  tcp_probe_ctx);
3426  if (NULL == buf)
3427  {
3428  GNUNET_CONNECTION_destroy(tcp_probe_ctx->sock);
3429  GNUNET_free(tcp_probe_ctx);
3430  return 0;
3431  }
3432  GNUNET_assert(size >= sizeof(tcp_probe_ctx->message));
3433  GNUNET_memcpy(buf, &tcp_probe_ctx->message, sizeof(tcp_probe_ctx->message));
3434  GNUNET_SERVER_connect_socket(tcp_probe_ctx->plugin->server,
3435  tcp_probe_ctx->sock);
3436  ret = sizeof(tcp_probe_ctx->message);
3437  GNUNET_free(tcp_probe_ctx);
3438  return ret;
3439 }
3440 
3441 
3451 static void
3453  const struct sockaddr *addr,
3454  socklen_t addrlen)
3455 {
3456  struct Plugin *plugin = cls;
3458  struct TCPProbeContext *tcp_probe_ctx;
3459 
3464  sock = GNUNET_CONNECTION_create_from_sockaddr(AF_INET, addr, addrlen);
3465  if (NULL == sock)
3466  {
3467  /* failed for some odd reason (out of sockets?); ignore attempt */
3468  return;
3469  }
3470 
3471  tcp_probe_ctx = GNUNET_new(struct TCPProbeContext);
3472  tcp_probe_ctx->message.header.size =
3473  htons(sizeof(struct TCP_NAT_ProbeMessage));
3474  tcp_probe_ctx->message.header.type =
3476  tcp_probe_ctx->message.clientIdentity = *plugin->env->my_identity;
3477  tcp_probe_ctx->plugin = plugin;
3478  tcp_probe_ctx->sock = sock;
3480  plugin->probe_tail,
3481  tcp_probe_ctx);
3482  tcp_probe_ctx->transmit_handle =
3484  ntohs(tcp_probe_ctx->message
3485  .header.size),
3488  tcp_probe_ctx);
3489 }
3490 
3491 
3499 static enum GNUNET_NetworkType
3500 tcp_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
3501 {
3502  return session->scope;
3503 }
3504 
3505 
3513 static enum GNUNET_NetworkType
3515  const struct GNUNET_HELLO_Address *address)
3516 {
3517  struct Plugin *plugin = cls;
3518  size_t addrlen;
3519  struct sockaddr_in a4;
3520  struct sockaddr_in6 a6;
3521  const struct IPv4TcpAddress *t4;
3522  const struct IPv6TcpAddress *t6;
3523  const void *sb;
3524  size_t sbs;
3525 
3526  addrlen = address->address_length;
3527  if (addrlen == sizeof(struct IPv6TcpAddress))
3528  {
3529  GNUNET_assert(NULL != address->address); /* make static analysis happy */
3530  t6 = address->address;
3531  memset(&a6, 0, sizeof(a6));
3532 #if HAVE_SOCKADDR_IN_SIN_LEN
3533  a6.sin6_len = sizeof(a6);
3534 #endif
3535  a6.sin6_family = AF_INET6;
3536  a6.sin6_port = t6->t6_port;
3537  GNUNET_memcpy(&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
3538  sb = &a6;
3539  sbs = sizeof(a6);
3540  }
3541  else if (addrlen == sizeof(struct IPv4TcpAddress))
3542  {
3543  GNUNET_assert(NULL != address->address); /* make static analysis happy */
3544  t4 = address->address;
3545  memset(&a4, 0, sizeof(a4));
3546 #if HAVE_SOCKADDR_IN_SIN_LEN
3547  a4.sin_len = sizeof(a4);
3548 #endif
3549  a4.sin_family = AF_INET;
3550  a4.sin_port = t4->t4_port;
3551  a4.sin_addr.s_addr = t4->ipv4_addr;
3552  sb = &a4;
3553  sbs = sizeof(a4);
3554  }
3555  else
3556  {
3557  GNUNET_break(0);
3558  return GNUNET_NT_UNSPECIFIED;
3559  }
3560  return plugin->env->get_address_type(plugin->env->cls, sb, sbs);
3561 }
3562 
3563 
3573 static int
3575  const struct GNUNET_PeerIdentity *peer,
3576  void *value)
3577 {
3578  struct Plugin *plugin = cls;
3579  struct GNUNET_ATS_Session *session = value;
3580 
3582  /* FIXME: cannot tell if this is up or not from current
3583  session state... */
3585  return GNUNET_OK;
3586 }
3587 
3588 
3601 static void
3604  void *sic_cls)
3605 {
3606  struct Plugin *plugin = cls;
3607 
3608  plugin->sic = sic;
3609  plugin->sic_cls = sic_cls;
3610  if (NULL != sic)
3611  {
3614  plugin);
3615  /* signal end of first iteration */
3616  sic(sic_cls, NULL, NULL);
3617  }
3618 }
3619 
3620 
3627 void *
3629 {
3630  static const struct GNUNET_SERVER_MessageHandler my_handlers[] =
3631  { { &handle_tcp_welcome,
3632  NULL,
3634  sizeof(struct WelcomeMessage) },
3636  NULL,
3638  sizeof(struct TCP_NAT_ProbeMessage) },
3640  { NULL, NULL, 0, 0 } };
3643  struct Plugin *plugin;
3645  unsigned long long aport;
3646  unsigned long long bport;
3647  unsigned long long max_connections;
3648  unsigned int i;
3649  struct GNUNET_TIME_Relative idle_timeout;
3650 
3651 #ifdef TCP_STEALTH
3652  struct GNUNET_NETWORK_Handle *const *lsocks;
3653 #endif
3654  int ret;
3655  int ret_s;
3656  struct sockaddr **addrs;
3657  socklen_t *addrlens;
3658 
3659  if (NULL == env->receive)
3660  {
3661  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
3662  initialze the plugin or the API */
3664  api->cls = NULL;
3668  return api;
3669  }
3670 
3671  GNUNET_assert(NULL != env->cfg);
3673  "transport-tcp",
3674  "MAX_CONNECTIONS",
3675  &max_connections))
3676  max_connections = 128;
3677 
3678  aport = 0;
3680  "transport-tcp",
3681  "PORT",
3682  &bport)) ||
3683  (bport > 65535) ||
3685  "transport-tcp",
3686  "ADVERTISED-PORT",
3687  &aport)) &&
3688  (aport > 65535)))
3689  {
3691  _("Require valid port number for service `%s' in configuration!\n"),
3692  "transport-tcp");
3693  return NULL;
3694  }
3695  if (0 == aport)
3696  aport = bport;
3697  if (0 == bport)
3698  aport = 0;
3699  if (0 != bport)
3700  {
3701  service = LEGACY_SERVICE_start("transport-tcp",
3702  env->cfg,
3704  if (NULL == service)
3705  {
3706  LOG(GNUNET_ERROR_TYPE_WARNING, _("Failed to start service.\n"));
3707  return NULL;
3708  }
3709  }
3710  else
3711  service = NULL;
3712 
3713  api = NULL;
3714  plugin = GNUNET_new(struct Plugin);
3715  plugin->sessionmap =
3717  plugin->max_connections = max_connections;
3718  plugin->open_port = bport;
3719  plugin->adv_port = aport;
3720  plugin->env = env;
3721  plugin->my_welcome.header.size = htons(sizeof(struct WelcomeMessage));
3722  plugin->my_welcome.header.type =
3723  htons(GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME);
3724  plugin->my_welcome.clientIdentity = *plugin->env->my_identity;
3725 
3726  if ((NULL != service) &&
3728  "transport-tcp",
3729  "TCP_STEALTH")))
3730  {
3731 #ifdef TCP_STEALTH
3733  lsocks = LEGACY_SERVICE_get_listen_sockets(service);
3734  if (NULL != lsocks)
3735  {
3736  uint32_t len = sizeof(struct WelcomeMessage);
3737 
3738  for (i = 0; NULL != lsocks[i]; i++)
3739  {
3740  if (
3741  (GNUNET_OK !=
3743  IPPROTO_TCP,
3744  TCP_STEALTH,
3745  env->my_identity,
3746  sizeof(
3747  struct GNUNET_PeerIdentity))) ||
3748  (GNUNET_OK !=
3750  IPPROTO_TCP,
3751  TCP_STEALTH_INTEGRITY_LEN,
3752  &len,
3753  sizeof(len))))
3754  {
3755  /* TCP STEALTH not supported by kernel */
3756  GNUNET_assert(0 == i);
3758  _("TCP_STEALTH not supported on this platform.\n"));
3759  goto die;
3760  }
3761  }
3762  }
3763 #else
3765  _("TCP_STEALTH not supported on this platform.\n"));
3766  goto die;
3767 #endif
3768  }
3769 
3770  if ((NULL != service) &&
3771  (GNUNET_SYSERR !=
3772  (ret_s =
3773  get_server_addresses("transport-tcp", env->cfg, &addrs, &addrlens))))
3774  {
3775  for (ret = ret_s - 1; ret >= 0; ret--)
3777  "Binding to address `%s'\n",
3778  GNUNET_a2s(addrs[ret], addrlens[ret]));
3779  plugin->nat = GNUNET_NAT_register(env->cfg,
3780  "transport-tcp",
3781  IPPROTO_TCP,
3782  (unsigned int)ret_s,
3783  (const struct sockaddr **)addrs,
3784  addrlens,
3787  plugin);
3788  for (ret = ret_s - 1; ret >= 0; ret--)
3789  GNUNET_free(addrs[ret]);
3790  GNUNET_free_non_null(addrs);
3791  GNUNET_free_non_null(addrlens);
3792  }
3793  else
3794  {
3795  plugin->nat = GNUNET_NAT_register(plugin->env->cfg,
3796  "transport-tcp",
3797  IPPROTO_TCP,
3798  0,
3799  NULL,
3800  NULL,
3801  NULL,
3803  plugin);
3804  }
3806  api->cls = plugin;
3807  api->send = &tcp_plugin_send;
3821  plugin->service = service;
3822  if (NULL != service)
3823  {
3824  plugin->server = LEGACY_SERVICE_get_server(service);
3825  }
3826  else
3827  {
3829  "transport-tcp",
3830  "TIMEOUT",
3831  &idle_timeout))
3832  {
3834  "transport-tcp",
3835  "TIMEOUT");
3836  goto die;
3837  }
3839  plugin,
3840  NULL,
3841  idle_timeout,
3842  GNUNET_YES);
3843  }
3844  plugin->handlers = GNUNET_malloc(sizeof(my_handlers));
3845  GNUNET_memcpy(plugin->handlers, my_handlers, sizeof(my_handlers));
3846  for (i = 0;
3847  i < sizeof(my_handlers) / sizeof(struct GNUNET_SERVER_MessageHandler);
3848  i++)
3849  plugin->handlers[i].callback_cls = plugin;
3850 
3851  GNUNET_SERVER_add_handlers(plugin->server, plugin->handlers);
3854  plugin->nat_wait_conns =
3856  if (0 != bport)
3858  _("TCP transport listening on port %llu\n"),
3859  bport);
3860  else
3862  _("TCP transport not listening on any port (client only)\n"));
3863  if ((aport != bport) && (0 != bport))
3865  _("TCP transport advertises itself as being on port %llu\n"),
3866  aport);
3867  /* Initially set connections to 0 */
3868  GNUNET_STATISTICS_set(plugin->env->stats,
3869  gettext_noop("# TCP sessions active"),
3870  0,
3871  GNUNET_NO);
3872  return api;
3873 
3874 die:
3875  if (NULL != plugin->nat)
3876  GNUNET_NAT_unregister(plugin->nat);
3878  if (NULL != service)
3879  LEGACY_SERVICE_stop(service);
3880  GNUNET_free(plugin);
3881  GNUNET_free_non_null(api);
3882  return NULL;
3883 }
3884 
3885 
3892 void *
3894 {
3895  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
3896  struct Plugin *plugin = api->cls;
3897  struct TCPProbeContext *tcp_probe;
3898  struct PrettyPrinterContext *cur;
3899  struct PrettyPrinterContext *next;
3900 
3901  if (NULL == plugin)
3902  {
3903  GNUNET_free(api);
3904  return NULL;
3905  }
3906  LOG(GNUNET_ERROR_TYPE_DEBUG, "Shutting down TCP plugin\n");
3907 
3908  /* Removing leftover sessions */
3911  plugin);
3912  /* Removing leftover NAT sessions */
3915  plugin);
3916 
3917  for (cur = plugin->ppc_dll_head; NULL != cur; cur = next)
3918  {
3919  next = cur->next;
3921  plugin->ppc_dll_tail,
3922  cur);
3924  cur->asc(cur->asc_cls, NULL, GNUNET_OK);
3925  GNUNET_free(cur);
3926  }
3927 
3928  if (NULL != plugin->service)
3929  LEGACY_SERVICE_stop(plugin->service);
3930  else
3931  GNUNET_SERVER_destroy(plugin->server);
3932  GNUNET_free(plugin->handlers);
3933  if (NULL != plugin->nat)
3934  GNUNET_NAT_unregister(plugin->nat);
3935  while (NULL != (tcp_probe = plugin->probe_head))
3936  {
3938  plugin->probe_tail,
3939  tcp_probe);
3940  GNUNET_CONNECTION_destroy(tcp_probe->sock);
3941  GNUNET_free(tcp_probe);
3942  }
3945  GNUNET_break(0 == plugin->cur_connections);
3946  GNUNET_free(plugin);
3947  GNUNET_free(api);
3948  return NULL;
3949 }
3950 
3951 /* 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:871
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:70
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:246
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?
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.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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:681
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:78
static int numeric
Option -n.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#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:181
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:1237
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.
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:686
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:76
struct GNUNET_PeerIdentity clientIdentity
Identity of the node connecting (TCP client)
static unsigned int size
Size of the "table".
Definition: peer.c:66
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:376
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:81
static void session_timeout(void *cls)
Session was idle for too long, so disconnect it.
configuration data
Definition: configuration.c:83
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:131
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:151
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:77
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:548
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_STRINGS_to_address_ip(const char *addr, uint16_t addrlen, struct sockaddr_storage *r_buf)
Tries to convert addr string to an IP (v4 or v6) address.
Definition: strings.c:1327
void * sic_cls
Closure for sic.
#define GNUNET_malloc(size)
Wrapper around malloc.
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:900
Category of last resort.
Definition: gnunet_nt_lib.h:39
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:956