GNUnet  0.19.4
gnunet-service-transport_neighbours.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2010-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  */
20 
26 #include "platform.h"
27 #include "gnunet_ats_service.h"
35 #include "gnunet_constants.h"
36 #include "transport.h"
37 
42 #define IGNORE_INBOUND_QUOTA GNUNET_YES
43 
47 #define NEIGHBOUR_TABLE_SIZE 256
48 
53 #define DISCONNECT_SENT_TIMEOUT GNUNET_TIME_relative_multiply ( \
54  GNUNET_TIME_UNIT_MILLISECONDS, 500)
55 
60 #define QUOTA_VIOLATION_DROP_THRESHOLD 10
61 
65 #define ATS_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply ( \
66  GNUNET_TIME_UNIT_SECONDS, 5)
67 
72 #define SETUP_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply ( \
73  GNUNET_TIME_UNIT_SECONDS, 15)
74 
81 #define FAST_RECONNECT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
82 
86 #define UTIL_TRANSMISSION_INTERVAL GNUNET_TIME_UNIT_SECONDS
87 
92 {
97 
103 
108  ACK_SEND_ACK = 2
109 };
110 
111 
113 
123 {
129 
134 
140 };
141 
142 
152 {
158 
163 };
164 
165 
172 {
177 
182 };
183 
184 
192 {
197 
202 
208 
214 
219 
226 };
227 
229 
230 
236 {
241 
246 
251 
255  void *cont_cls;
256 
261  const char *message_buf;
262 
267 
272 };
273 
274 
279 {
284 
289 
296 
301 
306 
311 
316 };
317 
318 
323 {
329 
335 
340 
345 
351 
355  struct GNUNET_PeerIdentity id;
356 
362 
367 
372 
378 
385 
390 
397 
402 
408  unsigned int quota_violation_count;
409 
416 
421 
426 
441 
446 
451 
456 };
457 
458 
463 
468 
473 
477 static unsigned int neighbours_connected;
478 
482 static unsigned long long bytes_in_send_queue;
483 
488 
489 
496 static char *
498 {
499  switch (s)
500  {
501  case ACK_UNDEFINED:
502  return "UNDEFINED";
503 
504  case ACK_SEND_SYN_ACK:
505  return "SEND_SYN_ACK";
506 
507  case ACK_SEND_ACK:
508  return "SEND_ACK";
509 
510  default:
511  GNUNET_break (0);
512  return "N/A";
513  }
514 }
515 
516 
524 static void
526 {
527  struct QuotaSetMessage q_msg;
528  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_min;
529 
531  return;
532 #if IGNORE_INBOUND_QUOTA
533  bandwidth_min = n->primary_address.bandwidth_out;
534 #else
537 #endif
538 
540  "Sending outbound quota of %u Bps for peer `%s' to all clients\n",
541  ntohl (bandwidth_min.value__),
542  GNUNET_i2s (&n->id));
543  q_msg.header.size = htons (sizeof(struct QuotaSetMessage));
545  q_msg.quota = bandwidth_min;
546  q_msg.peer = n->id;
548  GNUNET_NO);
549 }
550 
551 
557 static void
559 {
560  size_t len = sizeof(struct ConnectInfoMessage);
561  char buf[len] GNUNET_ALIGN;
562  struct ConnectInfoMessage *connect_msg = (struct ConnectInfoMessage *) buf;
563  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_min;
564 
565 #if IGNORE_INBOUND_QUOTA
566  bandwidth_min = n->primary_address.bandwidth_out;
567 #else
570 #endif
572  "We are now connected to peer `%s'\n",
573  GNUNET_i2s (&n->id));
574  connect_msg->header.size = htons (sizeof(buf));
575  connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
576  connect_msg->id = n->id;
577  connect_msg->quota_out = bandwidth_min;
578  GST_clients_broadcast (&connect_msg->header,
579  GNUNET_NO);
580 }
581 
582 
589 static void
591 {
593  "Peer `%s' disconnected\n",
594  GNUNET_i2s (&n->id));
597 }
598 
599 
611 static void
613  const struct GNUNET_HELLO_Address *address,
615  struct GNUNET_TIME_Absolute state_timeout,
617  bandwidth_in,
619  bandwidth_out)
620 {
621  (void) bandwidth_in;
622  (void) bandwidth_out;
624  "Notifying about change for peer `%s' with address `%s' in state `%s' timing out at %s\n",
625  GNUNET_i2s (peer),
629  /* FIXME: include bandwidth in notification! */
631  address,
632  state,
633  state_timeout);
634 }
635 
636 
643 static struct NeighbourMapEntry *
645 {
646  if (NULL == neighbours)
647  return NULL;
649 }
650 
651 
658 static int
660 {
661  if (NULL == n)
662  return GNUNET_NO;
664 }
665 
666 
674 static void
676 {
677  if (GNUNET_YES == na->ats_active)
679  GNUNET_NO);
680  if (NULL != na->address)
681  {
683  na->session);
685  na->address = NULL;
686  }
689  na->ats_active = GNUNET_NO;
690  na->keep_alive_nonce = 0;
691  na->session = NULL;
692 }
693 
694 
702 static void
703 master_task (void *cls);
704 
705 
713 static void
717 {
720  {
723  gettext_noop ("# peers connected"),
725  GNUNET_NO);
726  }
727  if ((! GNUNET_TRANSPORT_is_connected (s)) &&
729  {
731  gettext_noop ("# peers connected"),
733  GNUNET_NO);
735  }
736  n->state = s;
737  if ((timeout.abs_value_us < n->timeout.abs_value_us) &&
738  (NULL != n->task))
739  {
740  /* new timeout is earlier, reschedule master task */
743  &master_task,
744  n);
745  }
746  n->timeout = timeout;
748  "Neighbour `%s' changed state to %s with timeout %s\n",
749  GNUNET_i2s (&n->id),
754  n->state,
755  n->timeout,
758 }
759 
760 
772 static void
774  const struct GNUNET_HELLO_Address *address,
775  struct GNUNET_ATS_Session *session,
776  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
777  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
778 {
780 
781  if (NULL == (papi = GST_plugins_find (address->transport_name)))
782  {
783  GNUNET_break (0);
784  return;
785  }
786  if (session == n->alternative_address.session)
787  {
788  n->alternative_address.bandwidth_in = bandwidth_in;
789  n->alternative_address.bandwidth_out = bandwidth_out;
790  return;
791  }
792  if (NULL != n->alternative_address.address)
793  {
795  "Replacing existing alternative address with another one\n");
797  }
798  if (NULL == session)
799  session = papi->get_session (papi->cls,
800  address);
801  if (NULL == session)
802  {
804  "Failed to obtain new session for peer `%s' and address '%s'\n",
805  GNUNET_i2s (&address->peer),
808  gettext_noop ("# session creation failed"),
809  1,
810  GNUNET_NO);
811  return;
812  }
814  session);
816  "Neighbour `%s' configured alternative address %s\n",
817  GNUNET_i2s (&n->id),
819 
821  n->alternative_address.bandwidth_in = bandwidth_in;
822  n->alternative_address.bandwidth_out = bandwidth_out;
823  n->alternative_address.session = session;
829 }
830 
831 
848 static struct GNUNET_TIME_Relative
850  const void *msgbuf,
851  size_t msgbuf_size,
852  uint32_t priority,
854  unsigned int use_keepalive_timeout,
856  void *cont_cls)
857 {
860 
861  GNUNET_assert (NULL != n->primary_address.session);
862  if ((((NULL == (papi = GST_plugins_find (
863  n->primary_address.address->transport_name))) ||
864  (-1 == papi->send (papi->cls,
865  n->primary_address.session,
866  msgbuf,
867  msgbuf_size,
868  priority,
869  (result = (GNUNET_NO == use_keepalive_timeout) ?
870  timeout :
873  papi->
874  query_keepalive_factor (papi->cls))),
875  cont,
876  cont_cls)))) &&
877  (NULL != cont))
878  cont (cont_cls,
879  &n->id,
881  msgbuf_size,
882  0);
883  GST_neighbours_notify_data_sent (n->primary_address.address,
884  n->primary_address.session,
885  msgbuf_size);
886  GNUNET_break (NULL != papi);
887  return result;
888 }
889 
890 
897 static void
899 {
900  /* Notify monitoring about change */
901  if (NULL == n->primary_address.address)
902  return;
904  "Disabling primary address\n");
907  n->state,
908  n->timeout,
912 }
913 
914 
920 static void
922 {
923  struct MessageQueue *mq;
924 
926  "Freeing neighbour state of peer `%s'\n",
927  GNUNET_i2s (&n->id));
928  n->is_active = NULL; /* always free'd by its own continuation! */
929 
930  /* fail messages currently in the queue */
931  while (NULL != (mq = n->messages_head))
932  {
934  n->messages_tail,
935  mq);
936  if (NULL != mq->cont)
937  mq->cont (mq->cont_cls,
939  mq->message_buf_size,
940  0);
941  GNUNET_free (mq);
942  }
943  /* Mark peer as disconnected */
947  /* free addresses and mark as unused */
949 
950  if (NULL != n->alternative_address.address)
951  {
953  "Cleaning up alternative address\n");
955  }
958  &n->id,
959  n));
960 
961  /* Cancel address requests for this peer */
962  if (NULL != n->suggest_handle)
963  {
965  n->suggest_handle = NULL;
966  }
967 
968  /* Cancel the disconnect task */
969  if (NULL != n->delayed_disconnect_task)
970  {
972  n->delayed_disconnect_task = NULL;
973  }
974 
975  /* Cancel the master task */
976  if (NULL != n->task)
977  {
979  n->task = NULL;
980  }
981  /* free rest of memory */
982  GNUNET_free (n);
983 }
984 
985 
996 static void
998  const struct GNUNET_PeerIdentity *target,
999  int result,
1000  size_t payload,
1001  size_t physical)
1002 {
1003  struct NeighbourMapEntry *n;
1004 
1005  (void) cls;
1006  (void) result;
1007  (void) payload;
1008  (void) physical;
1009  n = lookup_neighbour (target);
1010  if (NULL == n)
1011  return; /* already gone */
1013  return; /* have created a fresh entry since */
1014  if (NULL != n->task)
1017 }
1018 
1019 
1025 static void
1027 {
1028  struct GNUNET_ATS_SessionDisconnectMessage disconnect_msg;
1029 
1031  "Sending DISCONNECT message to peer `%4s'\n",
1032  GNUNET_i2s (&n->id));
1033  disconnect_msg.header.size = htons (sizeof(struct
1035  disconnect_msg.header.type =
1037  disconnect_msg.reserved = htonl (0);
1038  disconnect_msg.purpose.size =
1039  htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
1040  + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
1041  + sizeof(struct GNUNET_TIME_AbsoluteNBO));
1042  disconnect_msg.purpose.purpose =
1044  disconnect_msg.timestamp =
1046  disconnect_msg.public_key = GST_my_identity.public_key;
1049  &disconnect_msg.purpose,
1050  &disconnect_msg.signature));
1051 
1052  (void) send_with_session (n,
1053  &disconnect_msg,
1054  sizeof(disconnect_msg),
1055  UINT32_MAX,
1057  GNUNET_NO,
1059  NULL);
1061  gettext_noop ("# DISCONNECT messages sent"),
1062  1,
1063  GNUNET_NO);
1064 }
1065 
1066 
1072 static void
1074 {
1076  "Disconnecting from peer %s in state %s\n",
1077  GNUNET_i2s (&n->id),
1079  /* depending on state, notify neighbour and/or upper layers of this peer
1080  about disconnect */
1081  switch (n->state)
1082  {
1085  /* other peer is completely unaware of us, no need to send DISCONNECT */
1086  free_neighbour (n);
1087  return;
1088 
1090  send_disconnect (n);
1094  break;
1095 
1097  /* we never ACK'ed the other peer's request, no need to send DISCONNECT */
1098  free_neighbour (n);
1099  return;
1100 
1102  /* we DID ACK the other peer's request, must send DISCONNECT */
1103  send_disconnect (n);
1107  break;
1108 
1112  /* we are currently connected, need to send disconnect and do
1113  internal notifications and update statistics */
1114  send_disconnect (n);
1118  break;
1119 
1121  /* Disconnecting while waiting for an ATS address to reconnect,
1122  * cannot send DISCONNECT */
1123  free_neighbour (n);
1124  return;
1125 
1127  /* already disconnected, ignore */
1128  break;
1129 
1131  /* already cleaned up, how did we get here!? */
1132  GNUNET_assert (0);
1133  break;
1134 
1135  default:
1137  "Unhandled state `%s'\n",
1139  GNUNET_break (0);
1140  break;
1141  }
1142  /* schedule timeout to clean up */
1143  if (NULL != n->task)
1146  &master_task,
1147  n);
1148 }
1149 
1150 
1161 static int
1164 {
1166  "Setting inbound quota of %u Bps for peer `%s' to all clients\n",
1167  ntohl (quota.value__), GNUNET_i2s (&n->id));
1169  quota);
1170  if (0 != ntohl (quota.value__))
1171  {
1172  struct GNUNET_ATS_SessionQuotaMessage sqm;
1173 
1174  sqm.header.size = htons (sizeof(struct GNUNET_ATS_SessionQuotaMessage));
1176  sqm.quota = quota.value__;
1177  if (NULL != n->primary_address.session)
1178  (void) send_with_session (n,
1179  &sqm,
1180  sizeof(sqm),
1181  UINT32_MAX - 1,
1183  GNUNET_NO,
1184  NULL, NULL);
1185  return GNUNET_YES;
1186  }
1188  "Disconnecting peer `%s' due to SET_QUOTA\n",
1189  GNUNET_i2s (&n->id));
1190  if (GNUNET_YES == test_connected (n))
1192  gettext_noop ("# disconnects due to quota of 0"),
1193  1, GNUNET_NO);
1195  return GNUNET_NO;
1196 }
1197 
1198 
1210 static void
1212  const struct GNUNET_HELLO_Address *address,
1213  struct GNUNET_ATS_Session *session,
1214  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
1215  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
1216 {
1217  if (session == n->primary_address.session)
1218  {
1220  GNUNET_YES);
1221  if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__)
1222  {
1223  n->primary_address.bandwidth_in = bandwidth_in;
1224  if (GNUNET_YES !=
1225  set_incoming_quota (n,
1226  bandwidth_in))
1227  return;
1228  }
1229  if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__)
1230  {
1231  n->primary_address.bandwidth_out = bandwidth_out;
1233  }
1234  return;
1235  }
1236  if ((NULL != n->primary_address.address) &&
1238  n->primary_address.address)))
1239  {
1240  GNUNET_break (0);
1241  return;
1242  }
1243  if (NULL == session)
1244  {
1245  GNUNET_break (0);
1247  session);
1248  return;
1249  }
1250  if (NULL != n->primary_address.address)
1251  {
1253  "Replacing existing primary address with another one\n");
1255  }
1257  n->primary_address.bandwidth_in = bandwidth_in;
1258  n->primary_address.bandwidth_out = bandwidth_out;
1259  n->primary_address.session = session;
1263  n->primary_address.session));
1264  /* subsystems about address use */
1266  GNUNET_YES);
1267  if (GNUNET_YES !=
1268  set_incoming_quota (n,
1269  bandwidth_in))
1270  return;
1273  "Neighbour `%s' switched to address `%s'\n",
1274  GNUNET_i2s (&n->id),
1276 
1279  n->state,
1280  n->timeout,
1283 }
1284 
1285 
1295 static void
1297  const struct GNUNET_PeerIdentity *receiver,
1298  int success,
1299  size_t size_payload,
1300  size_t physical)
1301 {
1302  struct MessageQueue *mq = cls;
1303  struct NeighbourMapEntry *n;
1304 
1305  if (NULL == (n = lookup_neighbour (receiver)))
1306  {
1307  if (NULL != mq->cont)
1308  mq->cont (mq->cont_cls,
1309  GNUNET_SYSERR /* not connected */,
1310  size_payload,
1311  0);
1312  GNUNET_free (mq);
1313  return; /* disconnect or other error while transmitting, can happen */
1314  }
1315  if (n->is_active == mq)
1316  {
1317  /* this is still "our" neighbour, remove us from its queue
1318  and allow it to send the next message now */
1319  n->is_active = NULL;
1320  if (NULL != n->task)
1323  n);
1324  }
1325  if (bytes_in_send_queue < mq->message_buf_size)
1326  {
1328  "Bytes_in_send_queue `%llu', Message_size %u, result: %s, payload %u, on wire %u\n",
1330  (unsigned int) mq->message_buf_size,
1331  (GNUNET_OK == success) ? "OK" : "FAIL",
1332  (unsigned int) size_payload,
1333  (unsigned int) physical);
1334  GNUNET_break (0);
1335  }
1336 
1337  GNUNET_break (size_payload == mq->message_buf_size);
1338  bytes_in_send_queue -= mq->message_buf_size;
1340  gettext_noop (
1341  "# bytes in message queue for other peers"),
1343  GNUNET_NO);
1344  if (GNUNET_OK == success)
1346  gettext_noop (
1347  "# messages transmitted to other peers"),
1348  1,
1349  GNUNET_NO);
1350  else
1352  gettext_noop
1353  (
1354  "# transmission failures for messages to other peers"),
1355  1, GNUNET_NO);
1357  "Sending message to `%s' of type %u with %u bytes was a %s\n",
1358  GNUNET_i2s (receiver),
1359  ntohs (((struct GNUNET_MessageHeader *) mq->message_buf)->type),
1360  (unsigned int) mq->message_buf_size,
1361  (success == GNUNET_OK) ? "success" : "FAILURE");
1362  if (NULL != mq->cont)
1363  mq->cont (mq->cont_cls,
1364  success,
1365  size_payload,
1366  physical);
1367  GNUNET_free (mq);
1368 }
1369 
1370 
1382 static void
1384 {
1385  struct MessageQueue *mq;
1387 
1388  if (NULL == n->primary_address.address)
1389  {
1390  /* no address, why are we here? */
1391  GNUNET_break (0);
1392  return;
1393  }
1394  if ((0 == n->primary_address.address->address_length) &&
1395  (NULL == n->primary_address.session))
1396  {
1397  /* no address, why are we here? */
1398  GNUNET_break (0);
1399  return;
1400  }
1401  if (NULL != n->is_active)
1402  {
1403  /* transmission already pending */
1404  return;
1405  }
1406 
1407  /* timeout messages from the queue that are past their due date */
1408  while (NULL != (mq = n->messages_head))
1409  {
1411  if (timeout.rel_value_us > 0)
1412  break;
1414  gettext_noop (
1415  "# messages timed out while in transport queue"),
1416  1,
1417  GNUNET_NO);
1419  n->messages_tail,
1420  mq);
1421  n->is_active = mq;
1423  &n->id,
1424  GNUNET_SYSERR,
1425  mq->message_buf_size,
1426  0); /* timeout */
1427  }
1428  if (NULL == mq)
1429  return; /* no more messages */
1430  if (NULL == n->primary_address.address)
1431  {
1432  /* transmit_send_continuation() caused us to drop session,
1433  can't try transmission anymore. */
1434  return;
1435  }
1436 
1437 
1439  n->messages_tail,
1440  mq);
1441  n->is_active = mq;
1442 
1444  "Giving message with %u bytes to plugin session %p\n",
1445  (unsigned int) mq->message_buf_size,
1447  (void) send_with_session (n,
1448  mq->message_buf,
1449  mq->message_buf_size,
1450  0 /* priority */,
1451  timeout,
1452  GNUNET_NO,
1454  mq);
1455 }
1456 
1457 
1466 static void
1468 {
1471  uint32_t nonce;
1472 
1476  return; /* no keepalive needed at this time */
1477 
1478  nonce = 0; /* 0 indicates 'not set' */
1479  while (0 == nonce)
1481  UINT32_MAX);
1482 
1484  "Sending KEEPALIVE to peer `%s' with nonce %u\n",
1485  GNUNET_i2s (&n->id),
1486  nonce);
1487  m.header.size = htons (sizeof(struct GNUNET_ATS_SessionKeepAliveMessage));
1488  m.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE);
1489  m.nonce = htonl (nonce);
1490 
1492  &m,
1493  sizeof(m),
1494  UINT32_MAX /* priority */,
1496  GNUNET_YES,
1497  NULL, NULL);
1499  gettext_noop ("# KEEPALIVES sent"),
1500  1,
1501  GNUNET_NO);
1502  n->primary_address.keep_alive_nonce = nonce;
1506 }
1507 
1508 
1516 void
1518  const struct GNUNET_MessageHeader *m)
1519 {
1520  struct NeighbourMapEntry *n;
1521  const struct GNUNET_ATS_SessionKeepAliveMessage *msg_in;
1523 
1524  if (sizeof(struct GNUNET_ATS_SessionKeepAliveMessage) != ntohs (m->size))
1525  {
1526  GNUNET_break_op (0);
1527  return;
1528  }
1529 
1530  msg_in = (const struct GNUNET_ATS_SessionKeepAliveMessage *) m;
1531  if (NULL == (n = lookup_neighbour (neighbour)))
1532  {
1534  gettext_noop
1535  ("# KEEPALIVE messages discarded (peer unknown)"),
1536  1, GNUNET_NO);
1537  return;
1538  }
1539  if (NULL == n->primary_address.session)
1540  {
1542  gettext_noop
1543  ("# KEEPALIVE messages discarded (no session)"),
1544  1, GNUNET_NO);
1545  return;
1546  }
1547 
1549  "Received KEEPALIVE request from peer `%s' with nonce %u\n",
1550  GNUNET_i2s (&n->id),
1551  ntohl (msg_in->nonce));
1553  gettext_noop (
1554  "# KEEPALIVES received in good order"),
1555  1,
1556  GNUNET_NO);
1557 
1558  /* send reply to allow neighbour to measure latency */
1559  msg.header.size = htons (sizeof(struct GNUNET_ATS_SessionKeepAliveMessage));
1560  msg.header.type = htons (
1562  msg.nonce = msg_in->nonce;
1563  (void) send_with_session (n,
1564  &msg,
1565  sizeof(struct GNUNET_ATS_SessionKeepAliveMessage),
1566  UINT32_MAX /* priority */,
1568  GNUNET_YES,
1569  NULL, NULL);
1570 }
1571 
1572 
1581 void
1583  const struct GNUNET_MessageHeader *m)
1584 {
1585  struct NeighbourMapEntry *n;
1587  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1588  struct GNUNET_TIME_Relative latency;
1589 
1590  if (sizeof(struct GNUNET_ATS_SessionKeepAliveMessage) != ntohs (m->size))
1591  {
1592  GNUNET_break_op (0);
1593  return;
1594  }
1595 
1596  msg = (const struct GNUNET_ATS_SessionKeepAliveMessage *) m;
1597  if (NULL == (n = lookup_neighbour (neighbour)))
1598  {
1600  gettext_noop (
1601  "# KEEPALIVE_RESPONSEs discarded (not connected)"),
1602  1,
1603  GNUNET_NO);
1604  return;
1605  }
1606  if ((GNUNET_TRANSPORT_PS_CONNECTED != n->state) ||
1608  {
1610  gettext_noop (
1611  "# KEEPALIVE_RESPONSEs discarded (not expected)"),
1612  1,
1613  GNUNET_NO);
1614  return;
1615  }
1616  if (NULL == n->primary_address.address)
1617  {
1619  gettext_noop (
1620  "# KEEPALIVE_RESPONSEs discarded (address changed)"),
1621  1,
1622  GNUNET_NO);
1623  return;
1624  }
1625  if (n->primary_address.keep_alive_nonce != ntohl (msg->nonce))
1626  {
1627  if (0 == n->primary_address.keep_alive_nonce)
1629  gettext_noop (
1630  "# KEEPALIVE_RESPONSEs discarded (no nonce)"),
1631  1,
1632  GNUNET_NO);
1633  else
1635  gettext_noop (
1636  "# KEEPALIVE_RESPONSEs discarded (bad nonce)"),
1637  1,
1638  GNUNET_NO);
1639  return;
1640  }
1642  gettext_noop (
1643  "# KEEPALIVE_RESPONSEs received (OK)"),
1644  1,
1645  GNUNET_NO);
1646 
1647 
1648  /* Update session timeout here */
1649  if (NULL != (papi = GST_plugins_find (
1651  {
1653  "Updating session for peer `%s' for session %p\n",
1654  GNUNET_i2s (&n->id),
1656  papi->update_session_timeout (papi->cls,
1657  &n->id,
1659  }
1660  else
1661  {
1662  GNUNET_break (0);
1663  }
1664 
1668  n->state,
1671 
1674  "Received KEEPALIVE_RESPONSE from peer `%s', latency is %s\n",
1675  GNUNET_i2s (&n->id),
1677  GNUNET_YES));
1679  GNUNET_TIME_relative_divide (latency,
1680  2));
1681 }
1682 
1683 
1696 struct GNUNET_TIME_Relative
1698  GNUNET_PeerIdentity *sender,
1699  ssize_t size,
1700  int *do_forward)
1701 {
1702  struct NeighbourMapEntry *n;
1703  struct GNUNET_TIME_Relative ret;
1704 
1705  if (NULL == neighbours)
1706  {
1707  *do_forward = GNUNET_NO;
1708  return GNUNET_TIME_UNIT_FOREVER_REL; /* This can happen during shutdown */
1709  }
1710  if (NULL == (n = lookup_neighbour (sender)))
1711  {
1713  gettext_noop (
1714  "# messages discarded due to lack of neighbour record"),
1715  1,
1716  GNUNET_NO);
1717  *do_forward = GNUNET_NO;
1718  return GNUNET_TIME_UNIT_ZERO;
1719  }
1720  if (! test_connected (n))
1721  {
1722  *do_forward = GNUNET_SYSERR;
1723  return GNUNET_TIME_UNIT_ZERO;
1724  }
1726  {
1727  n->quota_violation_count++;
1729  "Bandwidth quota (%u b/s) violation detected (total of %u).\n",
1732  /* Discount 32k per violation */
1733  GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, -32 * 1024);
1734  }
1735  else
1736  {
1737  if (n->quota_violation_count > 0)
1738  {
1739  /* try to add 32k back */
1741  n->quota_violation_count--;
1742  }
1743  }
1745  {
1747  gettext_noop
1748  ("# bandwidth quota violations by other peers"),
1749  1, GNUNET_NO);
1750  *do_forward = GNUNET_NO;
1752  }
1753  *do_forward = GNUNET_YES;
1755  if (ret.rel_value_us > 0)
1756  {
1758  "Throttling read (%lld bytes excess at %u b/s), waiting %s before reading more.\n",
1760  (unsigned int) n->in_tracker.available_bytes_per_s__,
1763  gettext_noop ("# ms throttling suggested"),
1764  (int64_t) ret.rel_value_us / 1000LL,
1765  GNUNET_NO);
1766  }
1767  return ret;
1768 }
1769 
1770 
1771 void
1773  const void *msg,
1774  size_t msg_size,
1777  void *cont_cls)
1778 {
1779  struct NeighbourMapEntry *n;
1780  struct MessageQueue *mq;
1781 
1782  /* All ove these cases should never happen; they are all API violations.
1783  But we check anyway, just to be sure. */
1784  if (NULL == (n = lookup_neighbour (target)))
1785  {
1786  GNUNET_break (0);
1787  if (NULL != cont)
1788  cont (cont_cls,
1789  GNUNET_SYSERR,
1790  msg_size,
1791  0);
1792  return;
1793  }
1794  if (GNUNET_YES != test_connected (n))
1795  {
1796  GNUNET_break (0);
1797  if (NULL != cont)
1798  cont (cont_cls,
1799  GNUNET_SYSERR,
1800  msg_size,
1801  0);
1802  return;
1803  }
1804  bytes_in_send_queue += msg_size;
1806  gettext_noop
1807  ("# bytes in message queue for other peers"),
1809  mq = GNUNET_malloc (sizeof(struct MessageQueue) + msg_size);
1810  mq->cont = cont;
1811  mq->cont_cls = cont_cls;
1812  GNUNET_memcpy (&mq[1], msg, msg_size);
1813  mq->message_buf = (const char *) &mq[1];
1814  mq->message_buf_size = msg_size;
1816 
1818  "Enqueueing %u bytes to send to peer %s\n",
1819  (unsigned int) msg_size,
1820  GNUNET_i2s (target));
1822  n->messages_tail,
1823  mq);
1824  if (NULL != n->task)
1827 }
1828 
1829 
1842 static void
1844  const struct GNUNET_PeerIdentity *target,
1845  int result,
1846  size_t size_payload,
1847  size_t size_on_wire)
1848 {
1849  struct NeighbourMapEntry *n;
1850 
1851  (void) cls;
1852  (void) size_payload;
1853  (void) size_on_wire;
1854  n = lookup_neighbour (target);
1855  if (NULL == n)
1856  {
1857  /* SYN continuation was called after neighbor was freed,
1858  * for example due to a time out for the state or the session
1859  * used was already terminated: nothing to do here... */
1860  return;
1861  }
1862 
1863  if ((GNUNET_TRANSPORT_PS_SYN_SENT != n->state) &&
1866  {
1867  /* SYN continuation was called after neighbor changed state,
1868  * for example due to a time out for the state or the session
1869  * used was already terminated: nothing to do here... */
1870  return;
1871  }
1872  if (GNUNET_OK == result)
1873  return;
1874 
1876  _ ("Failed to send SYN message to peer `%s'\n"),
1877  GNUNET_i2s (target));
1878  switch (n->state)
1879  {
1881  /* Remove address and request an additional one */
1887  break;
1888 
1890  /* Remove address and request an additional one */
1896  break;
1897 
1899  /* Remove address and request and go back to primary address */
1901  gettext_noop (
1902  "# Failed attempts to switch addresses (failed to send SYN CONT)"),
1903  1,
1904  GNUNET_NO);
1906  "Switch failed, cleaning up alternative address\n");
1912  break;
1913 
1914  default:
1916  break;
1917  }
1918 }
1919 
1920 
1926 static void
1928 {
1929  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1930  struct TransportSynMessage connect_msg;
1931  struct NeighbourMapEntry *n;
1932 
1933  GNUNET_assert (NULL != na->session);
1935  "Sending SYN message to peer `%s' at %s\n",
1936  GNUNET_i2s (&na->address->peer),
1937  GST_plugins_a2s (na->address));
1938 
1939  papi = GST_plugins_find (na->address->transport_name);
1940  GNUNET_assert (NULL != papi);
1942  gettext_noop
1943  ("# SYN messages sent"),
1944  1, GNUNET_NO);
1946  connect_msg.header.size = htons (sizeof(struct TransportSynMessage));
1948  connect_msg.reserved = htonl (0);
1950  if (-1 ==
1951  papi->send (papi->cls,
1952  na->session,
1953  (const char *) &connect_msg,
1954  sizeof(struct TransportSynMessage),
1955  UINT_MAX,
1957  &send_session_syn_cont, NULL))
1958  {
1960  _ ("Failed to transmit SYN message to %s\n"),
1961  GST_plugins_a2s (na->address));
1962  n = lookup_neighbour (&na->address->peer);
1963  if (NULL == n)
1964  {
1965  GNUNET_break (0);
1966  return;
1967  }
1968  switch (n->state)
1969  {
1971  /* Remove address and request and additional one */
1972  GNUNET_assert (na == &n->primary_address);
1978  /* Hard failure to send the SYN message with this address:
1979  Destroy address and session */
1980  break;
1981 
1983  /* Remove address and request an additional one */
1984  GNUNET_assert (na == &n->primary_address);
1990  break;
1991 
1993  GNUNET_assert (na == &n->alternative_address);
1995  gettext_noop (
1996  "# Failed attempts to switch addresses (failed to send SYN)"),
1997  1,
1998  GNUNET_NO);
1999  /* Remove address and request an additional one */
2001  "Switch failed, cleaning up alternative address\n");
2007  break;
2008 
2009  default:
2010  GNUNET_break (0);
2012  break;
2013  }
2014  return;
2015  }
2017  na->session,
2018  sizeof(struct TransportSynMessage));
2019 }
2020 
2021 
2034 static void
2036  const struct GNUNET_PeerIdentity *target,
2037  int result,
2038  size_t size_payload,
2039  size_t size_on_wire)
2040 {
2041  struct NeighbourMapEntry *n;
2042 
2043  (void) cls;
2044  (void) size_payload;
2045  (void) size_on_wire;
2046  n = lookup_neighbour (target);
2047  if (NULL == n)
2048  {
2049  /* SYN_ACK continuation was called after neighbor was freed,
2050  * for example due to a time out for the state or the session
2051  * used was already terminated: nothing to do here... */
2052  return;
2053  }
2054 
2056  {
2057  /* SYN_ACK continuation was called after neighbor changed state,
2058  * for example due to a time out for the state or the session
2059  * used was already terminated: nothing to do here... */
2060  return;
2061  }
2062  if (GNUNET_OK == result)
2063  return;
2064 
2066  _ (
2067  "Failed to send SYN_ACK message to peer `%s' using address `%s'\n"),
2068  GNUNET_i2s (target),
2070 
2071  /* Remove address and request and additional one */
2072  /* FIXME: what if the neighbour's primary address
2073  changed in the meantime? Might want to instead
2074  pass "something" around in closure to be sure. */
2081 }
2082 
2083 
2091 static void
2093  struct GNUNET_TIME_Absolute timestamp)
2094 {
2095  const struct GNUNET_HELLO_Address *address = na->address;
2096  struct GNUNET_ATS_Session *session = na->session;
2097  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2098  struct TransportSynMessage connect_msg;
2099  struct NeighbourMapEntry *n;
2100 
2102  "Sending SYN_ACK to peer `%s'\n",
2103  GNUNET_i2s (&address->peer));
2104 
2105  if (NULL == (papi = GST_plugins_find (address->transport_name)))
2106  {
2107  GNUNET_break (0);
2108  return;
2109  }
2110  if (NULL == session)
2111  session = papi->get_session (papi->cls,
2112  address);
2113  if (NULL == session)
2114  {
2115  GNUNET_break (0);
2116  return;
2117  }
2119  session);
2121  gettext_noop
2122  ("# SYN_ACK messages sent"),
2123  1, GNUNET_NO);
2124  connect_msg.header.size = htons (sizeof(struct TransportSynMessage));
2125  connect_msg.header.type = htons (
2127  connect_msg.reserved = htonl (0);
2128  connect_msg.timestamp = GNUNET_TIME_absolute_hton (timestamp);
2129 
2130  if (GNUNET_SYSERR ==
2131  papi->send (papi->cls,
2132  session,
2133  (const char *) &connect_msg,
2134  sizeof(struct TransportSynMessage),
2135  UINT_MAX,
2137  &send_session_syn_ack_cont, NULL))
2138  {
2140  _ ("Failed to transmit SYN_ACK message to %s\n"),
2142 
2143  n = lookup_neighbour (&address->peer);
2144  if (NULL == n)
2145  {
2146  GNUNET_break (0);
2147  return;
2148  }
2149  /* Remove address and request and additional one */
2156  return;
2157  }
2158 }
2159 
2160 
2169 static void
2171 {
2172  struct NeighbourMapEntry *n = cls;
2173  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2174  struct GNUNET_TIME_Relative delay;
2175  int do_forward;
2176 
2177  if (NULL == n->primary_address.address)
2178  return; /* not active, ignore */
2180  GNUNET_assert (NULL != papi);
2181  if (NULL == papi->update_inbound_delay)
2182  return;
2184  0,
2185  &do_forward);
2187  "New inbound delay for peer `%s' is %llu ms\n",
2188  GNUNET_i2s (&n->id),
2189  (unsigned long long) delay.rel_value_us / 1000LL);
2190  if (NULL == n->primary_address.session)
2191  return;
2192  papi->update_inbound_delay (papi->cls,
2193  &n->id,
2195  delay);
2196 }
2197 
2198 
2205 static struct NeighbourMapEntry *
2207 {
2208  struct NeighbourMapEntry *n;
2209 
2210  if (0 ==
2211  memcmp (&GST_my_identity,
2212  peer,
2213  sizeof(struct GNUNET_PeerIdentity)))
2214  {
2216  "Cowardly refusing to consider myself my neighbour!\n");
2217  return NULL;
2218  }
2220  "Creating new neighbour entry for `%s'\n",
2221  GNUNET_i2s (peer));
2222  n = GNUNET_new (struct NeighbourMapEntry);
2223  n->id = *peer;
2224  n->ack_state = ACK_UNDEFINED;
2229  n,
2238  &n->id,
2239  n,
2242  peer,
2243  0);
2244 
2245  return n;
2246 }
2247 
2248 
2253 {
2258 
2263 
2268 
2273 
2278 };
2279 
2280 
2289 int
2291  const struct GNUNET_PeerIdentity *peer)
2292 {
2293  const struct TransportSynMessage *scm;
2294  struct NeighbourMapEntry *n;
2295  struct GNUNET_TIME_Absolute ts;
2296 
2297  if (ntohs (message->size) != sizeof(struct TransportSynMessage))
2298  {
2299  GNUNET_break_op (0);
2300  return GNUNET_SYSERR;
2301  }
2303  gettext_noop
2304  ("# SYN messages received"),
2305  1, GNUNET_NO);
2306  if (NULL == neighbours)
2307  {
2309  _ (
2310  "SYN request from peer `%s' ignored due impending shutdown\n"),
2311  GNUNET_i2s (peer));
2312  return GNUNET_OK; /* we're shutting down */
2313  }
2314  scm = (const struct TransportSynMessage *) message;
2315  GNUNET_break_op (0 == ntohl (scm->reserved));
2317  if (0 ==
2318  memcmp (&GST_my_identity,
2319  peer,
2320  sizeof(struct GNUNET_PeerIdentity)))
2321  {
2322  /* loopback connection-to-self, ignore */
2323  return GNUNET_SYSERR;
2324  }
2325  n = lookup_neighbour (peer);
2326  if (NULL == n)
2327  {
2328  /* This is a new neighbour and set to not connected */
2329  n = setup_neighbour (peer);
2330  GNUNET_assert (NULL != n);
2331  }
2332 
2333  /* Remember this SYN message in neighbour */
2335  n->connect_ack_timestamp = ts;
2336 
2338  "Received SYN for peer `%s' in state %s/%s\n",
2339  GNUNET_i2s (peer),
2341  print_ack_state (n->ack_state));
2342 
2343  switch (n->state)
2344  {
2346  /* Request an address from ATS to send SYN_ACK to this peer */
2351  break;
2352 
2354  /* SYN message takes priority over us asking ATS for address:
2355  * Wait for ATS to suggest an address and send SYN_ACK */
2360  break;
2361 
2363  /* We already wait for an address to send an SYN_ACK */
2364  break;
2365 
2368  /* Send ACK immediately */
2369  n->ack_state = ACK_SEND_ACK;
2371  ts);
2372  break;
2373 
2375  /* we are already connected and can thus send the ACK immediately */
2376  GNUNET_assert (NULL != n->primary_address.address);
2377  GNUNET_assert (NULL != n->primary_address.session);
2378  n->ack_state = ACK_SEND_ACK;
2380  ts);
2381  break;
2382 
2384  /* We wait for ATS address suggestion */
2385  break;
2386 
2388  /* We received a SYN message while waiting for a SYN_ACK in fast
2389  * reconnect. Send SYN_ACK immediately */
2390  n->ack_state = ACK_SEND_ACK;
2393  break;
2394 
2396  /* We are already connected and can thus send the ACK immediately;
2397  still, it can never hurt to have an alternative address, so also
2398  tell ATS about it */
2399  GNUNET_assert (NULL != n->primary_address.address);
2400  GNUNET_assert (NULL != n->primary_address.session);
2401  n->ack_state = ACK_SEND_ACK;
2403  ts);
2404  break;
2405 
2407  /* Get rid of remains and re-try */
2408  free_neighbour (n);
2409  n = setup_neighbour (peer);
2410  GNUNET_assert (NULL != n);
2411  /* Remember the SYN time stamp for ACK message */
2413  n->connect_ack_timestamp = ts;
2414  /* Request an address for the peer */
2419  break;
2420 
2422  /* should not be possible */
2423  GNUNET_assert (0);
2424  break;
2425 
2426  default:
2428  "Unhandled state `%s'\n",
2430  GNUNET_break (0);
2431  return GNUNET_SYSERR;
2432  }
2433  return GNUNET_OK;
2434 }
2435 
2436 
2453 static int
2455  struct GNUNET_ATS_Session *session,
2456  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
2457  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
2458 {
2459  struct NeighbourMapEntry *n;
2460 
2461  n = lookup_neighbour (&address->peer);
2462  if ((NULL == n) ||
2463  (NULL == n->primary_address.address) ||
2465  n->primary_address.address)))
2466  return GNUNET_NO;
2467  /* We are not really switching addresses, but merely adjusting
2468  session and/or bandwidth, can do fast ATS update! */
2469  if (session != n->primary_address.session)
2470  {
2471  /* switch to a different session, but keeping same address; could
2472  happen if there is a 2nd inbound connection */
2473  n->primary_address.session = session;
2476  n->primary_address.session));
2477  }
2478  if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__)
2479  {
2480  n->primary_address.bandwidth_in = bandwidth_in;
2481  if (GNUNET_YES !=
2482  set_incoming_quota (n,
2483  bandwidth_in))
2484  return GNUNET_NO;
2485  }
2486  if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__)
2487  {
2488  n->primary_address.bandwidth_out = bandwidth_out;
2490  }
2491  return GNUNET_OK;
2492 }
2493 
2494 
2508 static void
2510  const struct GNUNET_PeerIdentity *peer,
2511  const struct GNUNET_HELLO_Address *address,
2512  struct GNUNET_ATS_Session *session,
2513  int result)
2514 {
2515  struct BlacklistCheckSwitchContext *blc_ctx = cls;
2516  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2517  struct NeighbourMapEntry *n;
2518 
2519  if (GNUNET_SYSERR == result)
2520  goto cleanup;
2521 
2522  papi = GST_plugins_find (address->transport_name);
2523  if (NULL == papi)
2524  {
2525  /* This can happen during shutdown. */
2526  goto cleanup;
2527  }
2528 
2529  if (GNUNET_NO == result)
2530  {
2532  "Blacklist denied to switch to suggested address `%s' session %p for peer `%s'\n",
2534  session,
2535  GNUNET_i2s (peer));
2537  "# ATS suggestions ignored (blacklist denied)",
2538  1,
2539  GNUNET_NO);
2540  if (NULL != session)
2541  papi->disconnect_session (papi->cls,
2542  session);
2543  if (GNUNET_YES !=
2547  NULL);
2548  goto cleanup;
2549  }
2550 
2551 
2552  if (NULL == session)
2553  {
2554  /* need to create a session, ATS only gave us an address */
2555  session = papi->get_session (papi->cls,
2556  address);
2558  "Obtained new session for peer `%s' and address '%s': %p\n",
2559  GNUNET_i2s (&address->peer),
2561  session);
2562  if (NULL != session)
2564  session);
2565  }
2566  if (NULL == session)
2567  {
2568  /* session creation failed, bad!, fail! */
2570  "# ATS suggestions ignored (failed to create session)",
2571  1,
2572  GNUNET_NO);
2573  /* No session could be obtained, remove blacklist check and clean up */
2575  "Failed to obtain new session for peer `%s' and address '%s'\n",
2576  GNUNET_i2s (&address->peer),
2579  session);
2580  goto cleanup;
2581  }
2582 
2583  /* We did this check already before going into blacklist, but
2584  it is theoretically possible that the situation changed in
2585  the meantime, hence we check again here */
2586  if (GNUNET_OK ==
2588  session,
2589  blc_ctx->bandwidth_in,
2590  blc_ctx->bandwidth_out))
2591  goto cleanup; /* was just a minor update, we're done */
2592 
2593  /* check if we also need to setup the neighbour entry */
2594  if (NULL == (n = lookup_neighbour (peer)))
2595  {
2596  n = setup_neighbour (peer);
2597  if (NULL == n)
2598  {
2599  /* not sure how this can happen... */
2600  GNUNET_break (0);
2601  goto cleanup;
2602  }
2604  }
2605 
2607  "Peer `%s' switches to address `%s'\n",
2608  GNUNET_i2s (&address->peer),
2610 
2611  switch (n->state)
2612  {
2614  GNUNET_break (0);
2616  session);
2617  free_neighbour (n);
2618  return;
2619 
2621  /* We requested an address and ATS suggests one:
2622  * set primary address and send SYN message*/
2624  address,
2625  session,
2626  blc_ctx->bandwidth_in,
2627  blc_ctx->bandwidth_out);
2628  if (ACK_SEND_SYN_ACK == n->ack_state)
2629  {
2630  /* Send pending SYN_ACK message */
2631  n->ack_state = ACK_SEND_ACK;
2634  }
2639  send_syn (&n->primary_address);
2640  break;
2641 
2643  /* ATS suggested a new address while waiting for an SYN_ACK:
2644  * Switch and send new SYN */
2645  /* ATS suggests a different address, switch again */
2647  address,
2648  session,
2649  blc_ctx->bandwidth_in,
2650  blc_ctx->bandwidth_out);
2651  if (ACK_SEND_SYN_ACK == n->ack_state)
2652  {
2653  /* Send pending SYN_ACK message */
2654  n->ack_state = ACK_SEND_ACK;
2657  }
2662  send_syn (&n->primary_address);
2663  break;
2664 
2666  /* We requested an address and ATS suggests one:
2667  * set primary address and send SYN_ACK message*/
2669  address,
2670  session,
2671  blc_ctx->bandwidth_in,
2672  blc_ctx->bandwidth_out);
2673  /* Send an ACK message as a response to the SYN msg */
2680  if ((ACK_SEND_SYN_ACK == n->ack_state) ||
2681  (ACK_UNDEFINED == n->ack_state))
2682  n->ack_state = ACK_SEND_ACK;
2683  break;
2684 
2686  /* ATS asks us to switch while we were trying to connect; switch to new
2687  address and check blacklist again */
2688  if ((ACK_SEND_SYN_ACK == n->ack_state))
2689  {
2690  n->ack_state = ACK_SEND_ACK;
2693  }
2695  address,
2696  session,
2697  blc_ctx->bandwidth_in,
2698  blc_ctx->bandwidth_out);
2703  break;
2704 
2706  GNUNET_assert (NULL != n->primary_address.address);
2707  GNUNET_assert (NULL != n->primary_address.session);
2708  GNUNET_break (n->primary_address.session != session);
2709  /* ATS asks us to switch a life connection; see if we can get
2710  a SYN_ACK on it before we actually do this! */
2712  address,
2713  session,
2714  blc_ctx->bandwidth_in,
2715  blc_ctx->bandwidth_out);
2721  gettext_noop ("# Attempts to switch addresses"),
2722  1,
2723  GNUNET_NO);
2725  break;
2726 
2729  address,
2730  session,
2731  blc_ctx->bandwidth_in,
2732  blc_ctx->bandwidth_out);
2733  if (ACK_SEND_SYN_ACK == n->ack_state)
2734  {
2735  /* Send pending SYN_ACK message */
2736  n->ack_state = ACK_SEND_ACK;
2739  }
2744  send_syn (&n->primary_address);
2745  break;
2746 
2748  /* ATS asks us to switch while we were trying to reconnect; switch to new
2749  address and send SYN again */
2751  address,
2752  session,
2753  blc_ctx->bandwidth_in,
2754  blc_ctx->bandwidth_out);
2759  send_syn (&n->primary_address);
2760  break;
2761 
2764  address)) &&
2765  (n->primary_address.session == session))
2766  {
2767  /* ATS switches back to still-active session */
2769  "ATS double-switched, cleaning up alternative address\n");
2773  n->timeout);
2774  break;
2775  }
2776  /* ATS asks us to switch a life connection, send */
2778  address,
2779  session,
2780  blc_ctx->bandwidth_in,
2781  blc_ctx->bandwidth_out);
2787  break;
2788 
2790  /* not going to switch addresses while disconnecting */
2792  "# ATS suggestion ignored (disconnecting)",
2793  1,
2794  GNUNET_NO);
2795  return;
2796 
2798  GNUNET_assert (0);
2799  break;
2800 
2801  default:
2803  "Unhandled state `%s'\n",
2805  GNUNET_break (0);
2806  break;
2807  }
2808 cleanup:
2811  blc_ctx);
2812  GNUNET_free (blc_ctx);
2813 }
2814 
2815 
2833 void
2835  struct GNUNET_ATS_Session *session,
2837  bandwidth_in,
2839  bandwidth_out)
2840 {
2841  struct GST_BlacklistCheck *blc;
2842  struct BlacklistCheckSwitchContext *blc_ctx;
2843 
2844  GNUNET_assert (NULL != address->transport_name);
2845  if (GNUNET_OK ==
2847  session,
2848  bandwidth_in,
2849  bandwidth_out))
2850  return;
2851 
2852  /* Check if plugin is available */
2853  if (NULL == (GST_plugins_find (address->transport_name)))
2854  {
2855  /* we don't have the plugin for this address */
2856  GNUNET_break (0);
2858  session);
2859  return;
2860  }
2861  if ((NULL == session) &&
2864  {
2865  /* This is a inbound address and we do not have a session to use! */
2866  GNUNET_break (0);
2868  session);
2869  return;
2870  }
2871 
2873  "ATS suggests address '%s' for peer `%s' at %u/%u speed\n",
2875  GNUNET_i2s (&address->peer),
2876  (unsigned int) ntohl (bandwidth_in.value__),
2877  (unsigned int) ntohl (bandwidth_out.value__));
2878 
2879  /* Perform blacklist check */
2880  blc_ctx = GNUNET_new (struct BlacklistCheckSwitchContext);
2881  blc_ctx->bandwidth_in = bandwidth_in;
2882  blc_ctx->bandwidth_out = bandwidth_out;
2885  blc_ctx);
2886  if (NULL != (blc = GST_blacklist_test_allowed (&address->peer,
2887  address->transport_name,
2889  blc_ctx,
2890  address,
2891  session)))
2892  {
2893  blc_ctx->blc = blc;
2894  }
2895 }
2896 
2897 
2907 static int
2909  const struct GNUNET_PeerIdentity *key,
2910  void *value)
2911 {
2912  struct NeighbourMapEntry *n = value;
2913  uint32_t bps_in;
2914  uint32_t bps_out;
2915  struct GNUNET_TIME_Relative delta;
2916 
2917  (void) cls;
2918  if ((GNUNET_YES != test_connected (n)) ||
2919  (NULL == n->primary_address.address))
2920  return GNUNET_OK;
2923  bps_in = 0;
2924  if ((0 != n->util_total_bytes_recv) && (0 != delta.rel_value_us))
2925  bps_in = (1000LL * 1000LL * n->util_total_bytes_recv)
2926  / (delta.rel_value_us);
2927  bps_out = 0;
2928  if ((0 != n->util_total_bytes_sent) && (0 != delta.rel_value_us))
2929  bps_out = (1000LL * 1000LL * n->util_total_bytes_sent) / delta.rel_value_us;
2930 
2932  "`%s' total: received %u Bytes/s, sent %u Bytes/s\n",
2933  GNUNET_i2s (key),
2934  bps_in,
2935  bps_out);
2937  bps_in,
2938  bps_out);
2939  n->util_total_bytes_recv = 0;
2940  n->util_total_bytes_sent = 0;
2942  return GNUNET_OK;
2943 }
2944 
2945 
2951 static void
2953 {
2954  (void) cls;
2955  util_transmission_tk = NULL;
2958  NULL);
2962  NULL);
2963 }
2964 
2965 
2974 void
2976  const struct GNUNET_MessageHeader *message)
2977 {
2978  struct NeighbourMapEntry *n;
2979 
2980  n = lookup_neighbour (&address->peer);
2981  if (NULL == n)
2982  return;
2983  n->util_total_bytes_recv += ntohs (message->size);
2984 }
2985 
2986 
2996 void
2998  struct GNUNET_ATS_Session *session,
2999  size_t size)
3000 {
3001  struct NeighbourMapEntry *n;
3002 
3003  n = lookup_neighbour (&address->peer);
3004  if (NULL == n)
3005  return;
3006  if (n->primary_address.session != session)
3007  return;
3009 }
3010 
3011 
3012 static void
3013 master_task (void *cls)
3014 {
3015  struct NeighbourMapEntry *n = cls;
3016  struct GNUNET_TIME_Relative delay;
3017 
3018  n->task = NULL;
3021  "Master task runs for neighbour `%s' in state %s with timeout in %s\n",
3022  GNUNET_i2s (&n->id),
3025  GNUNET_YES));
3026  switch (n->state)
3027  {
3029  /* invalid state for master task, clean up */
3030  GNUNET_break (0);
3031  free_neighbour (n);
3032  return;
3033 
3035  if (0 == delay.rel_value_us)
3036  {
3038  "Connection to `%s' timed out waiting for ATS to provide address\n",
3039  GNUNET_i2s (&n->id));
3040  free_neighbour (n);
3041  return;
3042  }
3043  break;
3044 
3046  if (0 == delay.rel_value_us)
3047  {
3049  "Connection to `%s' timed out waiting for other peer to send SYN_ACK\n",
3050  GNUNET_i2s (&n->id));
3051  /* Remove address and request and additional one */
3057  return;
3058  }
3059  break;
3060 
3062  if (0 == delay.rel_value_us)
3063  {
3065  "Connection to `%s' timed out waiting ATS to provide address to use for SYN_ACK\n",
3066  GNUNET_i2s (&n->id));
3067  free_neighbour (n);
3068  return;
3069  }
3070  break;
3071 
3073  if (0 == delay.rel_value_us)
3074  {
3076  "Connection to `%s' timed out waiting for other peer to send ACK\n",
3077  GNUNET_i2s (&n->id));
3079  return;
3080  }
3081  break;
3082 
3084  if (0 == delay.rel_value_us)
3085  {
3087  "Connection to `%s' timed out, missing KEEPALIVE_RESPONSEs\n",
3088  GNUNET_i2s (&n->id));
3090  return;
3091  }
3093  send_keepalive (n);
3094  break;
3095 
3097  if (0 == delay.rel_value_us)
3098  {
3100  "Connection to `%s' timed out, waiting for ATS replacement address\n",
3101  GNUNET_i2s (&n->id));
3103  return;
3104  }
3105  break;
3106 
3108  if (0 == delay.rel_value_us)
3109  {
3111  "Connection to `%s' timed out, waiting for other peer to SYN_ACK replacement address\n",
3112  GNUNET_i2s (&n->id));
3114  return;
3115  }
3116  break;
3117 
3119  if (0 == delay.rel_value_us)
3120  {
3122  "Switch failed, cleaning up alternative address\n");
3128  }
3130  send_keepalive (n);
3131  break;
3132 
3135  "Cleaning up connection to `%s' after sending DISCONNECT\n",
3136  GNUNET_i2s (&n->id));
3137  free_neighbour (n);
3138  return;
3139 
3141  /* how did we get here!? */
3142  GNUNET_assert (0);
3143  break;
3144 
3145  default:
3147  "Unhandled state `%s'\n",
3149  GNUNET_break (0);
3150  break;
3151  }
3155  {
3156  /* if we are *now* in one of the two states, we're sending
3157  keep alive messages, so we need to consider the keepalive
3158  delay, not just the connection timeout */
3160  n->keep_alive_time),
3161  delay);
3162  }
3163  if (NULL == n->task)
3165  &master_task,
3166  n);
3167 }
3168 
3169 
3176 static void
3178 {
3179  struct GNUNET_MessageHeader msg;
3180 
3182  "Sending ACK message to peer `%s'\n",
3183  GNUNET_i2s (&n->id));
3184 
3185  msg.size = htons (sizeof(struct GNUNET_MessageHeader));
3187  (void) send_with_session (n,
3188  &msg,
3189  sizeof(struct GNUNET_MessageHeader),
3190  UINT32_MAX,
3192  GNUNET_NO,
3193  NULL, NULL);
3194 }
3195 
3196 
3208 int
3210  GNUNET_MessageHeader *message,
3211  const struct
3213  struct GNUNET_ATS_Session *session)
3214 {
3215  const struct TransportSynMessage *scm;
3216  struct GNUNET_TIME_Absolute ts;
3217  struct NeighbourMapEntry *n;
3218 
3219  (void) session;
3220  if (ntohs (message->size) != sizeof(struct TransportSynMessage))
3221  {
3222  GNUNET_break_op (0);
3223  return GNUNET_SYSERR;
3224  }
3226  gettext_noop
3227  ("# SYN_ACK messages received"),
3228  1, GNUNET_NO);
3229  scm = (const struct TransportSynMessage *) message;
3230  GNUNET_break_op (ntohl (scm->reserved) == 0);
3231  if (NULL == (n = lookup_neighbour (&address->peer)))
3232  {
3234  gettext_noop
3235  ("# unexpected SYN_ACK messages (no peer)"),
3236  1, GNUNET_NO);
3237  return GNUNET_SYSERR;
3238  }
3240  "Received SYN_ACK message from peer `%s' in state %s/%s\n",
3241  GNUNET_i2s (&address->peer),
3243  print_ack_state (n->ack_state));
3245  switch (n->state)
3246  {
3248  GNUNET_break (0);
3249  free_neighbour (n);
3250  return GNUNET_SYSERR;
3251 
3254  gettext_noop (
3255  "# unexpected SYN_ACK messages (not ready)"),
3256  1,
3257  GNUNET_NO);
3258  break;
3259 
3262  {
3264  "SYN_ACK ignored as the timestamp does not match our SYN request\n");
3265  return GNUNET_OK;
3266  }
3277  break;
3278 
3282  gettext_noop (
3283  "# unexpected SYN_ACK messages (not ready)"),
3284  1,
3285  GNUNET_NO);
3286  break;
3287 
3289  /* duplicate SYN_ACK, let's answer by duplicate ACK just in case */
3291  break;
3292 
3294  /* we didn't expect any SYN_ACK, as we are waiting for ATS
3295  to give us a new address... */
3297  gettext_noop (
3298  "# unexpected SYN_ACK messages (waiting on ATS)"),
3299  1,
3300  GNUNET_NO);
3301  break;
3302 
3304  /* Reconnecting with new address address worked; go back to connected! */
3310  break;
3311 
3313  /* new address worked; adopt it and go back to connected! */
3319 
3320  /* Set primary addresses */
3327  gettext_noop (
3328  "# Successful attempts to switch addresses"),
3329  1,
3330  GNUNET_NO);
3331 
3333  memset (&n->alternative_address,
3334  0,
3335  sizeof(n->alternative_address));
3337  break;
3338 
3341  gettext_noop
3342  ("# unexpected SYN_ACK messages (disconnecting)"),
3343  1, GNUNET_NO);
3344  return GNUNET_SYSERR;
3345 
3347  GNUNET_assert (0);
3348  break;
3349 
3350  default:
3352  "Unhandled state `%s'\n",
3354  GNUNET_break (0);
3355  return GNUNET_SYSERR;
3356  }
3357  return GNUNET_OK;
3358 }
3359 
3360 
3370 int
3372  struct GNUNET_ATS_Session *session)
3373 {
3374  struct NeighbourMapEntry *n;
3375 
3376  if (NULL == (n = lookup_neighbour (peer)))
3377  return GNUNET_NO; /* can't affect us */
3378  if (session != n->primary_address.session)
3379  {
3380  /* Free alternative address */
3381  if (session == n->alternative_address.session)
3382  {
3386  n->timeout);
3388  "Session died, cleaning up alternative address\n");
3390  }
3391  return GNUNET_NO; /* doesn't affect us further */
3392  }
3393 
3395  /* The session for neighbour's primary address died */
3396  switch (n->state)
3397  {
3399  GNUNET_break (0);
3400  free_neighbour (n);
3401  return GNUNET_YES;
3402 
3404  GNUNET_break (0);
3405  free_neighbour (n);
3406  return GNUNET_YES;
3407 
3409  /* The session used to send the SYN terminated:
3410  * this implies a connect error*/
3412  "Failed to send SYN in CONNECT_SENT with `%s' %p: session terminated\n",
3415 
3416  /* Destroy the address since it cannot be used */
3422  break;
3423 
3426  /* error on inbound session; free neighbour entirely */
3427  free_neighbour (n);
3428  return GNUNET_YES;
3429 
3431  /* Our primary connection died, try a fast reconnect */
3437  break;
3438 
3440  /* we don't have an address, how can it go down? */
3441  GNUNET_break (0);
3442  break;
3443 
3446  "Failed to send SYN in RECONNECT_SENT with `%s' %p: session terminated\n",
3449  /* Destroy the address since it cannot be used */
3455  break;
3456 
3458  /* primary went down while we were waiting for SYN_ACK on secondary;
3459  secondary as primary */
3460 
3462  "Connection `%s' %p to peer `%s' was terminated while switching, "
3463  "switching to alternative address `%s' %p\n",
3466  GNUNET_i2s (peer),
3469 
3470  /* Destroy the inbound address since it cannot be used */
3475  n->primary_address.session));
3476  memset (&n->alternative_address,
3477  0,
3478  sizeof(struct NeighbourAddress));
3483  break;
3484 
3487  break;
3488 
3490  /* neighbour was freed and plugins told to terminate session */
3491  return GNUNET_NO;
3492 
3493  default:
3495  "Unhandled state `%s'\n",
3497  GNUNET_break (0);
3498  break;
3499  }
3500  if (NULL != n->task)
3503  return GNUNET_YES;
3504 }
3505 
3506 
3517 int
3519  const struct GNUNET_HELLO_Address *address,
3520  struct GNUNET_ATS_Session *session)
3521 {
3522  struct NeighbourMapEntry *n;
3523 
3524  (void) session;
3525  if (ntohs (message->size) != sizeof(struct GNUNET_MessageHeader))
3526  {
3527  GNUNET_break_op (0);
3528  return GNUNET_SYSERR;
3529  }
3531  gettext_noop ("# ACK messages received"),
3532  1,
3533  GNUNET_NO);
3534  if (NULL == (n = lookup_neighbour (&address->peer)))
3535  {
3536  GNUNET_break_op (0);
3537  return GNUNET_SYSERR;
3538  }
3540  "Received ACK for peer `%s' in state %s/%s\n",
3541  GNUNET_i2s (&address->peer),
3543  print_ack_state (n->ack_state));
3544 
3545  /* Check if we are in a plausible state for having sent
3546  a SYN_ACK. If not, return, otherwise break.
3547 
3548  The remote peers sends a ACK as a response for a SYN_ACK
3549  message.
3550 
3551  We expect a ACK:
3552  - If a remote peer has sent a SYN, we responded with a SYN_ACK and
3553  now wait for the ACK to finally be connected
3554  - If we sent a SYN_ACK to this peer before */if (((GNUNET_TRANSPORT_PS_SYN_RECV_ACK != n->state) &&
3555  (ACK_SEND_ACK != n->ack_state)) ||
3556  (NULL == n->primary_address.address))
3557  {
3559  "Received unexpected ACK message from peer `%s' in state %s/%s\n",
3560  GNUNET_i2s (&address->peer),
3562  print_ack_state (n->ack_state));
3563 
3565  gettext_noop ("# unexpected ACK messages"),
3566  1,
3567  GNUNET_NO);
3568  return GNUNET_OK;
3569  }
3571  {
3572  /* We tried to switch addresses while being connect. We explicitly wait
3573  * for a SYN_ACK before going to GNUNET_TRANSPORT_PS_CONNECTED,
3574  * so we do not want to set the address as in use! */
3575  return GNUNET_OK;
3576  }
3581 
3582  if (NULL == n->primary_address.address)
3583  {
3584  /* See issue #3693.
3585  * We are in state = PSY_SYN_RECV_ACK or ack_state = ACK_SEND_ACK, which
3586  * really means we did try (and succeed) to send a SYN and are waiting for
3587  * an ACK.
3588  * That suggests that the primary_address used to be non-NULL, but maybe it
3589  * got reset to NULL without the state being changed appropriately?
3590  */GNUNET_break (0);
3591  return GNUNET_OK;
3592  }
3593 
3594  /* Reset backoff for primary address */
3597  return GNUNET_OK;
3598 }
3599 
3600 
3607 int
3609 {
3610  return test_connected (lookup_neighbour (target));
3611 }
3612 
3613 
3619 static void
3621 {
3622  struct NeighbourMapEntry *n = cls;
3623 
3624  n->delayed_disconnect_task = NULL;
3626  "Disconnecting by request from peer %s\n",
3627  GNUNET_i2s (&n->id));
3628  free_neighbour (n);
3629 }
3630 
3631 
3632 void
3634  const struct GNUNET_MessageHeader *msg)
3635 {
3636  struct NeighbourMapEntry *n;
3637  const struct GNUNET_ATS_SessionQuotaMessage *sqm;
3638  struct GNUNET_BANDWIDTH_Value32NBO last;
3639 
3641  "Received QUOTA message from peer `%s'\n",
3642  GNUNET_i2s (peer));
3643  if (ntohs (msg->size) != sizeof(struct GNUNET_ATS_SessionQuotaMessage))
3644  {
3645  GNUNET_break_op (0);
3647  gettext_noop (
3648  "# quota messages ignored (malformed)"),
3649  1,
3650  GNUNET_NO);
3651  return;
3652  }
3654  gettext_noop
3655  ("# QUOTA messages received"),
3656  1, GNUNET_NO);
3657  sqm = (const struct GNUNET_ATS_SessionQuotaMessage *) msg;
3658  if (NULL == (n = lookup_neighbour (peer)))
3659  {
3660  /* gone already */
3661  return;
3662  }
3665  sqm->quota)));
3666  if (last.value__ != n->neighbour_receive_quota.value__)
3667  {
3668  n->neighbour_receive_quota = last;
3670  }
3671 }
3672 
3673 
3681 void
3684  const struct
3686 {
3687  struct NeighbourMapEntry *n;
3688  const struct GNUNET_ATS_SessionDisconnectMessage *sdm;
3689 
3691  "Received DISCONNECT message from peer `%s'\n",
3692  GNUNET_i2s (peer));
3693  if (ntohs (msg->size) != sizeof(struct GNUNET_ATS_SessionDisconnectMessage))
3694  {
3695  GNUNET_break_op (0);
3697  gettext_noop
3698  ("# disconnect messages ignored (malformed)"),
3699  1,
3700  GNUNET_NO);
3701  return;
3702  }
3704  gettext_noop
3705  ("# DISCONNECT messages received"),
3706  1, GNUNET_NO);
3707  sdm = (const struct GNUNET_ATS_SessionDisconnectMessage *) msg;
3708  if (NULL == (n = lookup_neighbour (peer)))
3709  {
3710  /* gone already */
3711  return;
3712  }
3715  {
3717  gettext_noop (
3718  "# disconnect messages ignored (timestamp)"),
3719  1,
3720  GNUNET_NO);
3721  return;
3722  }
3723  if (0 != memcmp (peer,
3724  &sdm->public_key,
3725  sizeof(struct GNUNET_PeerIdentity)))
3726  {
3727  GNUNET_break_op (0);
3728  return;
3729  }
3730  if (ntohl (sdm->purpose.size) !=
3731  sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
3732  + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
3733  + sizeof(struct GNUNET_TIME_AbsoluteNBO))
3734  {
3736  "DISCONNECT message from peer `%s' has invalid size\n",
3737  GNUNET_i2s (peer));
3738  GNUNET_break_op (0);
3739  return;
3740  }
3741  if (GNUNET_OK !=
3744  &sdm->purpose,
3745  &sdm->signature,
3746  &sdm->public_key))
3747  {
3749  "DISCONNECT message from peer `%s' cannot be verified \n",
3750  GNUNET_i2s (peer));
3751  GNUNET_break_op (0);
3752  return;
3753  }
3754  if (NULL == n->delayed_disconnect_task)
3755  {
3757  n);
3758  }
3759 }
3760 
3761 
3766 {
3771 
3775  void *cb_cls;
3776 };
3777 
3778 
3787 static int
3789  const struct GNUNET_PeerIdentity *key,
3790  void *value)
3791 {
3792  struct IteratorContext *ic = cls;
3793  struct NeighbourMapEntry *n = value;
3794  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
3795  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
3796 
3797  (void) key;
3798  if (NULL != n->primary_address.address)
3799  {
3800  bandwidth_in = n->primary_address.bandwidth_in;
3801  bandwidth_out = n->primary_address.bandwidth_out;
3802  }
3803  else
3804  {
3805  bandwidth_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
3806  bandwidth_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
3807  }
3808  ic->cb (ic->cb_cls,
3809  &n->id,
3811  n->state,
3812  n->timeout,
3813  bandwidth_in, bandwidth_out);
3814  return GNUNET_OK;
3815 }
3816 
3817 
3824 void
3826  void *cb_cls)
3827 {
3828  struct IteratorContext ic;
3829 
3830  if (NULL == neighbours)
3831  return; /* can happen during shutdown */
3832  ic.cb = cb;
3833  ic.cb_cls = cb_cls;
3836  &ic);
3837 }
3838 
3839 
3845 void
3847 {
3848  struct NeighbourMapEntry *n;
3849 
3850  if (NULL == (n = lookup_neighbour (target)))
3851  return; /* not active */
3852  if (GNUNET_YES == test_connected (n))
3854  gettext_noop (
3855  "# disconnected from peer upon explicit request"),
3856  1,
3857  GNUNET_NO);
3859  "Forced disconnect from peer %s\n",
3860  GNUNET_i2s (target));
3862 }
3863 
3864 
3871 const struct GNUNET_HELLO_Address *
3873 {
3874  struct NeighbourMapEntry *n;
3875 
3876  n = lookup_neighbour (peer);
3877  if (NULL == n)
3878  return NULL;
3879  return n->primary_address.address;
3880 }
3881 
3882 
3888 void
3889 GST_neighbours_start (unsigned int max_fds)
3890 {
3891  (void) max_fds;
3893  GNUNET_NO);
3897  NULL);
3898 }
3899 
3900 
3909 static int
3911  const struct GNUNET_PeerIdentity *key,
3912  void *value)
3913 {
3914  struct NeighbourMapEntry *n = value;
3915 
3916  (void) cls;
3917  (void) key;
3919  "Disconnecting peer `%4s' during shutdown\n",
3920  GNUNET_i2s (&n->id));
3921  free_neighbour (n);
3922  return GNUNET_OK;
3923 }
3924 
3925 
3929 void
3931 {
3932  if (NULL == neighbours)
3933  return;
3934  if (NULL != util_transmission_tk)
3935  {
3937  util_transmission_tk = NULL;
3938  }
3941  NULL);
3943  neighbours = NULL;
3944 }
3945 
3946 
3947 /* end of file gnunet-service-transport_neighbours.c */
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define gettext_noop(String)
Definition: gettext.h:70
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
static char * address
GNS address for this phone.
static void cleanup(void *cls)
Function scheduled as very last function, cleans up after us.
struct GNUNET_HashCode key
The key used in the DHT.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static char * value
Value of the record to add/remove.
enum State state
current state of profiling
static int result
Global testing status.
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
#define MAX_BANDWIDTH_CARRY_S
Number of seconds that available bandwidth carries over (can accumulate).
static unsigned long long payload
How much data are we currently storing in the database?
static unsigned long long quota
How much space are we allowed to use?
static char buf[2048]
static struct GNUNET_PeerIdentity GST_my_identity
Our public key.
static struct GNUNET_CRYPTO_EddsaPrivateKey * GST_my_private_key
Our private key.
static struct GNUNET_STATISTICS_Handle * GST_stats
Statistics handle.
struct GNUNET_ATS_ConnectivityHandle * GST_ats_connect
ATS connectivity handle.
struct GST_BlacklistCheck * GST_blacklist_test_allowed(const struct GNUNET_PeerIdentity *peer, const char *transport_name, GST_BlacklistTestContinuation cont, void *cont_cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
Test if a peer/transport combination is blacklisted.
void GST_clients_broadcast(const struct GNUNET_MessageHeader *msg, int may_drop)
Broadcast the given message to all of our clients.
void GST_clients_broadcast_disconnect(const struct GNUNET_PeerIdentity *peer)
Notify all clients about a disconnect, and cancel pending SEND_OK messages for this peer.
void GST_clients_broadcast_peer_notification(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout)
Broadcast the new active address to all clients monitoring the peer.
void GST_ats_block_address(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
Temporarily block a valid address for use by ATS for address suggestions.
int GST_ats_is_known(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
Test if ATS knows about this address and session.
void GST_ats_new_session(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
Notify ATS about a new session now existing for the given address.
void GST_ats_block_reset(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
Reset address blocking time.
void GST_ats_update_delay(const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Relative delay)
Notify ATS about delay changes to properties of an address.
void GST_ats_update_utilization(const struct GNUNET_HELLO_Address *address, uint32_t bps_in, uint32_t bps_out)
Notify ATS about utilization changes to an address.
interfacing between transport and ATS service
void GST_manipulation_peer_disconnect(const struct GNUNET_PeerIdentity *peer)
Notify manipulation about disconnect so it can discard queued messages.
static void master_task(void *cls)
Master task run for every neighbour.
#define NEIGHBOUR_TABLE_SIZE
Size of the neighbour hash map.
static void transmit_send_continuation(void *cls, const struct GNUNET_PeerIdentity *receiver, int success, size_t size_payload, size_t physical)
We're done with our transmission attempt, continue processing.
static void unset_primary_address(struct NeighbourMapEntry *n)
Clear the primary address of a neighbour since this address is not valid anymore and notify monitorin...
void GST_neighbours_switch_to_address(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
For the given peer, switch to this address.
#define SETUP_CONNECTION_TIMEOUT
How long are we willing to wait for an ACK from the other peer before giving up on our connect operat...
static void utilization_transmission(void *cls)
Task transmitting utilization in a regular interval.
static void neighbours_connect_notification(struct NeighbourMapEntry *n)
Notify our clients that another peer connected to us.
void GST_neighbours_notify_data_recv(const struct GNUNET_HELLO_Address *address, const struct GNUNET_MessageHeader *message)
Track information about data we received from the given address (used to notify ATS about our utiliza...
void GST_neighbours_keepalive_response(const struct GNUNET_PeerIdentity *neighbour, const struct GNUNET_MessageHeader *m)
We received a KEEP_ALIVE_RESPONSE message and use this to calculate latency to this peer.
const struct GNUNET_HELLO_Address * GST_neighbour_get_current_address(const struct GNUNET_PeerIdentity *peer)
Obtain current address information for the given neighbour.
static void send_syn(struct NeighbourAddress *na)
Send a SYN message via the given address.
void GST_neighbours_handle_disconnect_message(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *msg)
We received a disconnect message from the given peer, validate and process.
static void send_disconnect(struct NeighbourMapEntry *n)
Transmit a DISCONNECT message to the other peer.
int GST_neighbours_handle_session_syn(const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *peer)
We received a 'SYN' message from the other peer.
static void neighbours_changed_notification(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
Notify transport clients that a neighbour peer changed its active address.
static void try_transmission_to_peer(struct NeighbourMapEntry *n)
Check the message list for the given neighbour and if we can send a message, do so.
static void send_session_syn_ack_cont(void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire)
Continuation called from our attempt to transmitted our GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN_ACK...
static void delayed_disconnect(void *cls)
Task to asynchronously run free_neighbour().
static int test_connected(struct NeighbourMapEntry *n)
Test if we're connected to the given peer.
static unsigned int neighbours_connected
counter for connected neighbours
static void set_state_and_timeout(struct NeighbourMapEntry *n, enum GNUNET_TRANSPORT_PeerState s, struct GNUNET_TIME_Absolute timeout)
Set net state and state timeout for this neighbour and notify monitoring.
static void send_session_syn_cont(void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire)
Continuation called from our attempt to transmitted our GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN to ...
struct GNUNET_TIME_Relative GST_neighbours_calculate_receive_delay(const struct GNUNET_PeerIdentity *sender, ssize_t size, int *do_forward)
We have received a message from the given sender.
static void send_outbound_quota_to_clients(struct NeighbourMapEntry *n)
Send information about a new outbound quota to our clients.
static void send_disconnect_cont(void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t payload, size_t physical)
Function called when the 'DISCONNECT' message has been sent by the plugin.
int GST_neighbours_handle_session_ack(const struct GNUNET_MessageHeader *message, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
We received a 'ACK' message from the other peer.
int GST_neighbours_handle_session_syn_ack(const struct GNUNET_MessageHeader *message, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
We received a 'SESSION_SYN_ACK' message from the other peer.
static struct BlacklistCheckSwitchContext * pending_bc_head
List of pending blacklist checks: head.
int GST_neighbours_session_terminated(const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Session *session)
A session was terminated.
static struct BlacklistCheckSwitchContext * pending_bc_tail
List of pending blacklist checks: tail.
void GST_neighbours_keepalive(const struct GNUNET_PeerIdentity *neighbour, const struct GNUNET_MessageHeader *m)
Keep the connection to the given neighbour alive longer, we received a KEEPALIVE (or equivalent); sen...
static struct GNUNET_TIME_Relative send_with_session(struct NeighbourMapEntry *n, const void *msgbuf, size_t msgbuf_size, uint32_t priority, struct GNUNET_TIME_Relative timeout, unsigned int use_keepalive_timeout, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
Transmit a message using the current session of the given neighbour.
static void send_session_ack_message(struct NeighbourMapEntry *n)
Send a ACK message to the neighbour to confirm that we got its SYN_ACK.
static void send_syn_ack_message(struct NeighbourAddress *na, struct GNUNET_TIME_Absolute timestamp)
Send a SYN_ACK message via the given address.
static void free_address(struct NeighbourAddress *na)
We don't need a given neighbour address any more.
#define ATS_RESPONSE_TIMEOUT
How long are we willing to wait for a response from ATS before timing out?
static int send_utilization_data(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Function called to send network utilization data to ATS for each active connection.
static int disconnect_all_neighbours(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Disconnect from the given neighbour.
static struct GNUNET_CONTAINER_MultiPeerMap * neighbours
Hash map from peer identities to the respective struct NeighbourMapEntry.
void GST_neighbours_force_disconnect(const struct GNUNET_PeerIdentity *target)
If we have an active connection to the given target, it must be shutdown.
static void switch_address_bl_check_cont(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, int result)
We've been asked to switch addresses, and just now got the result from the blacklist check to see if ...
static void set_alternative_address(struct NeighbourMapEntry *n, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
Initialize the alternative address of a neighbour.
static int try_run_fast_ats_update(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
Check if the given address is the same that we are already using for the respective neighbour.
void GST_neighbours_send(const struct GNUNET_PeerIdentity *target, const void *msg, size_t msg_size, struct GNUNET_TIME_Relative timeout, GST_NeighbourSendContinuation cont, void *cont_cls)
Transmit a message to the given target using the active connection.
#define QUOTA_VIOLATION_DROP_THRESHOLD
How often must a peer violate bandwidth quotas before we start to simply drop its messages?
static struct NeighbourMapEntry * setup_neighbour(const struct GNUNET_PeerIdentity *peer)
Create a fresh entry in the neighbour map for the given peer.
static void set_primary_address(struct NeighbourMapEntry *n, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
Initialize the primary address of a neighbour.
static void neighbours_disconnect_notification(struct NeighbourMapEntry *n)
Notify our clients (and manipulation) that a peer disconnected from us.
static void disconnect_neighbour(struct NeighbourMapEntry *n)
Disconnect from the given neighbour, clean up the record.
#define DISCONNECT_SENT_TIMEOUT
Time we give plugin to transmit DISCONNECT message before the neighbour entry self-destructs.
static void inbound_bw_tracker_update(void *cls)
Function called by the bandwidth tracker for a peer whenever the tracker's state changed such that we...
void GST_neighbours_stop()
Cleanup the neighbours subsystem.
static void free_neighbour(struct NeighbourMapEntry *n)
Free a neighbour map entry.
GST_ACK_State
State describing which kind a reply this neighbour should send.
@ ACK_SEND_SYN_ACK
The neighbour received a SYN message and has to send a SYN_ACK as reply.
@ ACK_SEND_ACK
The neighbour sent a SYN_ACK message and has to send a ACK as reply.
@ ACK_UNDEFINED
We did not receive a SYN message for this neighbour.
static struct NeighbourMapEntry * lookup_neighbour(const struct GNUNET_PeerIdentity *pid)
Lookup a neighbour entry in the neighbours hash map.
int GST_neighbours_test_connected(const struct GNUNET_PeerIdentity *target)
Test if we're connected to the given peer.
static void send_keepalive(struct NeighbourMapEntry *n)
Send keepalive message to the neighbour.
static int set_incoming_quota(struct NeighbourMapEntry *n, struct GNUNET_BANDWIDTH_Value32NBO quota)
Change the incoming quota for the given peer.
void GST_neighbours_iterate(GST_NeighbourIterator cb, void *cb_cls)
Iterate over all connected neighbours.
static char * print_ack_state(enum GST_ACK_State s)
Convert the given ACK state to a string.
#define FAST_RECONNECT_TIMEOUT
How long are we willing to wait for a successful reconnect if an existing connection went down?...
void GST_neighbours_start(unsigned int max_fds)
Initialize the neighbours subsystem.
static struct GNUNET_SCHEDULER_Task * util_transmission_tk
Task transmitting utilization data.
void GST_neighbours_notify_data_sent(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, size_t size)
Track information about data we transmitted using the given address and session (used to notify ATS a...
static unsigned long long bytes_in_send_queue
Number of bytes we have currently queued for transmission.
void GST_neighbours_handle_quota_message(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *msg)
We received a quota message from the given peer, validate and process.
static int neighbours_iterate(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Call the callback from the closure for each neighbour.
#define UTIL_TRANSMISSION_INTERVAL
Interval to send utilization data.
neighbour manipulation API, allows manipulation of performance metrics (delay and towards ATS)
void(* GST_NeighbourSendContinuation)(void *cls, int success, size_t bytes_payload, size_t bytes_on_wire)
Function called after the transmission is done.
void(* GST_NeighbourIterator)(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
Function called for each neighbour.
struct GNUNET_TRANSPORT_PluginFunctions * GST_plugins_find(const char *name)
Obtain the plugin API based on a plugin name.
const char * GST_plugins_a2s(const struct GNUNET_HELLO_Address *address)
Convert a given address to a human-readable format.
void GST_validation_set_address_use(const struct GNUNET_HELLO_Address *address, int in_use)
Update if we are using an address for a connection actively right now.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
Automatic transport selection and outbound bandwidth determination.
Maintain the list of currently known hosts.
struct GNUNET_ATS_ConnectivitySuggestHandle * GNUNET_ATS_connectivity_suggest(struct GNUNET_ATS_ConnectivityHandle *ch, const struct GNUNET_PeerIdentity *peer, uint32_t strength)
We would like to receive address suggestions for a peer.
void GNUNET_ATS_connectivity_suggest_cancel(struct GNUNET_ATS_ConnectivitySuggestHandle *sh)
We no longer care about being connected to a peer.
int GNUNET_BANDWIDTH_tracker_consume(struct GNUNET_BANDWIDTH_Tracker *av, ssize_t size)
Notify the tracker that a certain number of bytes of bandwidth have been consumed.
Definition: bandwidth.c:368
void GNUNET_BANDWIDTH_tracker_update_quota(struct GNUNET_BANDWIDTH_Tracker *av, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit)
Update quota of bandwidth tracker.
Definition: bandwidth.c:492
struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_init(uint32_t bytes_per_second)
Create a new bandwidth value.
Definition: bandwidth.c:40
struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_max(struct GNUNET_BANDWIDTH_Value32NBO b1, struct GNUNET_BANDWIDTH_Value32NBO b2)
Compute the MAX of two bandwidth values.
Definition: bandwidth.c:73
void GNUNET_BANDWIDTH_tracker_init(struct GNUNET_BANDWIDTH_Tracker *av, GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb, void *update_cb_cls, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit, uint32_t max_carry_s)
Initialize bandwidth tracker.
Definition: bandwidth.c:279
struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_min(struct GNUNET_BANDWIDTH_Value32NBO b1, struct GNUNET_BANDWIDTH_Value32NBO b2)
Compute the MIN of two bandwidth values.
Definition: bandwidth.c:57
struct GNUNET_TIME_Relative GNUNET_BANDWIDTH_tracker_get_delay(struct GNUNET_BANDWIDTH_Tracker *av, size_t size)
Compute how long we should wait until consuming size bytes of bandwidth in order to stay within the g...
Definition: bandwidth.c:424
#define GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT
Bandwidth (in/out) to assume initially (before either peer has communicated any particular preference...
#define GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT
How long do we delay reading more from a peer after a quota violation?
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition: crypto_ecc.c:619
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_verify_(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EddsaSignature *sig, const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Verify EdDSA signature.
Definition: crypto_ecc.c:702
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_HELLO_address_free(addr)
Free an address.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:99
int GNUNET_HELLO_address_check_option(const struct GNUNET_HELLO_Address *address, enum GNUNET_HELLO_AddressInfo option)
Check if an address has a local option set.
Definition: address.c:39
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:112
@ GNUNET_HELLO_ADDRESS_INFO_INBOUND
This is an inbound address and cannot be used to initiate an outbound connection to another peer.
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_log(kind,...)
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT
Message from TRANSPORT notifying about a client that connected to us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA
Message exchanged between transport services to indicate that the sender should limit its transmissio...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE
Message send by a peer to notify the other to keep the session alive and measure latency in a regular...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE
Response to a GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE message to measure latency in a regular...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK
Transport ACK message exchanged between transport services to indicate that a SYN_ACK message was acc...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT
Transport DISCONNECT message exchanged between transport services to indicate that a connection shoul...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN
Transport SYN message exchanged between transport services to indicate that a session should be marke...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN_ACK
Transport SYN_ACK message exchanged between transport services to indicate that a SYN message was acc...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA
Message telling transport to limit its receive rate.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1299
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition: scheduler.c:1249
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1272
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:343
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:436
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:405
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:616
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:737
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:550
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:569
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition: time.c:421
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:638
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
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".
const char * GNUNET_TRANSPORT_ps2s(enum GNUNET_TRANSPORT_PeerState state)
Convert a transport state to a human readable string.
GNUNET_TRANSPORT_PeerState
Possible state of a neighbour.
int GNUNET_TRANSPORT_is_connected(enum GNUNET_TRANSPORT_PeerState state)
Check if a state is defined as connected.
@ GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED
We're finished with the disconnect; and are cleaning up the state now! We put the struct into this st...
@ GNUNET_TRANSPORT_PS_NOT_CONNECTED
Fresh peer or completely disconnected.
@ GNUNET_TRANSPORT_PS_INIT_ATS
Asked to initiate connection, trying to get address from ATS.
@ GNUNET_TRANSPORT_PS_SYN_RECV_ATS
Received a SYN, asking ATS about address suggestions.
@ GNUNET_TRANSPORT_PS_SYN_RECV_ACK
SYN request from other peer was SYN_ACK'ed, waiting for ACK.
@ GNUNET_TRANSPORT_PS_RECONNECT_SENT
Sent SYN over new address (either by ATS telling us to switch addresses or from RECONNECT_ATS); if th...
@ GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT
We have some primary connection, but ATS suggested we switch to some alternative; we now sent a SYN m...
@ GNUNET_TRANSPORT_PS_CONNECTED
Got our SYN_ACK/ACK, connection is up.
@ GNUNET_TRANSPORT_PS_SYN_SENT
Sent SYN message to other peer, waiting for SYN_ACK.
@ GNUNET_TRANSPORT_PS_RECONNECT_ATS
Connection got into trouble, rest of the system still believes it to be up, but we're getting a new a...
@ GNUNET_TRANSPORT_PS_DISCONNECT
Disconnect in progress (we're sending the DISCONNECT message to the other peer; after that is finishe...
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
void receiver(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback to read from the SOCKS5 proxy.
Definition: socks.c:330
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
Entry in a DLL we use to keep track of pending blacklist checks.
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in
Inbound bandwidth that was assigned to address.
struct BlacklistCheckSwitchContext * prev
DLL prev pointer.
struct BlacklistCheckSwitchContext * next
DLL next pointer.
struct GST_BlacklistCheck * blc
Handle to the blacklist check we are performing.
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out
Outbound bandwidth that was assigned to address.
Message from the transport service to the library informing about neighbors.
Definition: transport.h:118
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT.
Definition: transport.h:122
struct GNUNET_PeerIdentity id
Identity of the new neighbour.
Definition: transport.h:141
struct GNUNET_BANDWIDTH_Value32NBO quota_out
Current outbound quota for this peer.
Definition: transport.h:135
Handle for ATS address suggestion requests.
Message we send to the other peer to notify it that we intentionally are disconnecting (to reduce tim...
struct GNUNET_TIME_AbsoluteNBO timestamp
Absolute time at the sender.
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose of the signature.
struct GNUNET_CRYPTO_EddsaSignature signature
Signature of the peer that sends us the disconnect.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Public key of the sender.
Message a peer sends to another when connected to indicate that a session is in use and the peer is s...
uint32_t nonce
A nonce to identify the session the keep alive is used for.
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE or GNUNET_MESSAGE_TYPE_TRANSPORT_SESSI...
Message a peer sends to another when connected to indicate that the other peer should limit transmiss...
uint32_t quota
Quota to use (for sending), in bytes per second.
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA.
Session handle for connections.
Struct to track available bandwidth.
int64_t consumption_since_last_update__
Number of bytes consumed since we last updated the tracker.
uint32_t available_bytes_per_s__
Bandwidth limit to enforce in bytes per second.
32-bit bandwidth used for network exchange by GNUnet, in bytes per second.
uint32_t value__
The actual value (bytes per second).
Internal representation of the hash map.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
an ECC signature using EdDSA.
An address for communicating with a peer.
const char * transport_name
Name of the transport plugin enabling the communication using this address.
size_t address_length
Number of bytes in address.
struct GNUNET_PeerIdentity peer
For which peer is this an address?
Header for all communications.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
void * cls
Closure for all of the callbacks.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
GNUNET_TRANSPORT_UpdateInboundDelay update_inbound_delay
Function that will be called whenever the transport service wants to notify the plugin that the inbou...
GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout
Function that will be called whenever the transport service wants to notify the plugin that a session...
Context we use when performing a blacklist check.
Closure for the neighbours_iterate() function.
GST_NeighbourIterator cb
Function to call on each connected neighbour.
For each neighbour we keep a list of messages that we still want to transmit to the neighbour.
void * cont_cls
Closure for cont.
struct MessageQueue * prev
This is a doubly linked list.
const char * message_buf
The message(s) we want to transmit, GNUNET_MessageHeader(s) stuck together in memory.
struct MessageQueue * next
This is a doubly linked list.
GST_NeighbourSendContinuation cont
Function to call once we're done.
size_t message_buf_size
Size of the message buf.
struct GNUNET_TIME_Absolute timeout
At what time should we fail?
A possible address we could use to communicate with a neighbour.
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in
Inbound bandwidth from ATS for this address.
struct GNUNET_TIME_Absolute connect_timestamp
Timestamp of the 'SESSION_CONNECT' message we sent to the other peer for this address.
uint32_t keep_alive_nonce
The current nonce sent in the last keep alive messages.
struct GNUNET_HELLO_Address * address
Network-level address information.
struct GNUNET_ATS_Session * session
Active session for this address.
int ats_active
Did we tell ATS that this is our 'active' address?
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out
Outbound bandwidth from ATS for this address.
int expect_latency_response
Did we sent an KEEP_ALIVE message and are we expecting a response?
uint32_t util_total_bytes_sent
Tracking utilization of outbound bandwidth.
struct NeighbourAddress primary_address
Primary address we currently use to communicate with the neighbour.
enum GNUNET_TRANSPORT_PeerState state
The current state of the peer.
struct GNUNET_TIME_Absolute connect_ack_timestamp
Timestamp we should include in our next SYN_ACK message.
unsigned int quota_violation_count
How often has the other peer (recently) violated the inbound traffic limit? Incremented by 10 per vio...
struct MessageQueue * messages_head
Head of list of messages we would like to send to this peer; must contain at most one message per cli...
struct GNUNET_TIME_Absolute last_util_transmission
Date of last utilization transmission.
struct NeighbourAddress alternative_address
Alternative address currently under consideration for communicating with the neighbour.
struct GNUNET_TIME_Absolute keep_alive_time
At what time should we sent the next keep-alive message?
struct GNUNET_BANDWIDTH_Tracker in_tracker
Tracker for inbound bandwidth.
struct GNUNET_BANDWIDTH_Value32NBO neighbour_receive_quota
Latest quota the other peer send us in bytes per second.
enum GST_ACK_State ack_state
When a peer wants to connect we have to reply to the 1st SYN message with a SYN_ACK message.
struct GNUNET_TIME_Absolute timeout
Time where we should cut the connection (timeout) if we don't make progress in the state machine (or ...
struct GNUNET_TIME_Absolute last_keep_alive_time
At what time did we sent the last keep-alive message? Used to calculate round-trip time ("latency").
struct GNUNET_SCHEDULER_Task * task
Main task that drives this peer (timeouts, keepalives, etc.).
struct GNUNET_ATS_ConnectivitySuggestHandle * suggest_handle
ATS address suggest handle.
struct MessageQueue * is_active
Are we currently trying to send a message? If so, which one?
uint32_t util_total_bytes_recv
Tracking utilization of inbound bandwidth.
struct GNUNET_PeerIdentity id
Identity of this neighbour.
struct MessageQueue * messages_tail
Tail of list of messages we would like to send to this peer; must contain at most one message per cli...
struct GNUNET_SCHEDULER_Task * delayed_disconnect_task
Task to disconnect neighbour after we received a DISCONNECT message.
Message used to set a particular bandwidth quota.
Definition: transport.h:176
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA.
Definition: transport.h:180
struct GNUNET_BANDWIDTH_Value32NBO quota
Quota.
Definition: transport.h:185
struct GNUNET_PeerIdentity peer
About which peer are we talking here?
Definition: transport.h:190
Message a peer sends to another to indicate that it intends to setup a connection/session for data ex...
struct GNUNET_TIME_AbsoluteNBO timestamp
Absolute time at the sender.
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN or GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN...
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
common internal definitions for transport service