GNUnet  0.11.x
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 
1781 void
1783  const void *msg,
1784  size_t msg_size,
1787  void *cont_cls)
1788 {
1789  struct NeighbourMapEntry *n;
1790  struct MessageQueue *mq;
1791 
1792  /* All ove these cases should never happen; they are all API violations.
1793  But we check anyway, just to be sure. */
1794  if (NULL == (n = lookup_neighbour (target)))
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  if (GNUNET_YES != test_connected (n))
1805  {
1806  GNUNET_break (0);
1807  if (NULL != cont)
1808  cont (cont_cls,
1809  GNUNET_SYSERR,
1810  msg_size,
1811  0);
1812  return;
1813  }
1814  bytes_in_send_queue += msg_size;
1816  gettext_noop
1817  ("# bytes in message queue for other peers"),
1819  mq = GNUNET_malloc (sizeof(struct MessageQueue) + msg_size);
1820  mq->cont = cont;
1821  mq->cont_cls = cont_cls;
1822  GNUNET_memcpy (&mq[1], msg, msg_size);
1823  mq->message_buf = (const char *) &mq[1];
1824  mq->message_buf_size = msg_size;
1826 
1828  "Enqueueing %u bytes to send to peer %s\n",
1829  (unsigned int) msg_size,
1830  GNUNET_i2s (target));
1832  n->messages_tail,
1833  mq);
1834  if (NULL != n->task)
1837 }
1838 
1839 
1852 static void
1854  const struct GNUNET_PeerIdentity *target,
1855  int result,
1856  size_t size_payload,
1857  size_t size_on_wire)
1858 {
1859  struct NeighbourMapEntry *n;
1860 
1861  (void) cls;
1862  (void) size_payload;
1863  (void) size_on_wire;
1864  n = lookup_neighbour (target);
1865  if (NULL == n)
1866  {
1867  /* SYN continuation was called after neighbor was freed,
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 
1873  if ((GNUNET_TRANSPORT_PS_SYN_SENT != n->state) &&
1876  {
1877  /* SYN continuation was called after neighbor changed state,
1878  * for example due to a time out for the state or the session
1879  * used was already terminated: nothing to do here... */
1880  return;
1881  }
1882  if (GNUNET_OK == result)
1883  return;
1884 
1886  _ ("Failed to send SYN message to peer `%s'\n"),
1887  GNUNET_i2s (target));
1888  switch (n->state)
1889  {
1891  /* Remove address and request an additional one */
1897  break;
1898 
1900  /* Remove address and request an additional one */
1906  break;
1907 
1909  /* Remove address and request and go back to primary address */
1911  gettext_noop (
1912  "# Failed attempts to switch addresses (failed to send SYN CONT)"),
1913  1,
1914  GNUNET_NO);
1916  "Switch failed, cleaning up alternative address\n");
1922  break;
1923 
1924  default:
1926  break;
1927  }
1928 }
1929 
1930 
1936 static void
1938 {
1939  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1940  struct TransportSynMessage connect_msg;
1941  struct NeighbourMapEntry *n;
1942 
1943  GNUNET_assert (NULL != na->session);
1945  "Sending SYN message to peer `%s' at %s\n",
1946  GNUNET_i2s (&na->address->peer),
1947  GST_plugins_a2s (na->address));
1948 
1949  papi = GST_plugins_find (na->address->transport_name);
1950  GNUNET_assert (NULL != papi);
1952  gettext_noop
1953  ("# SYN messages sent"),
1954  1, GNUNET_NO);
1956  connect_msg.header.size = htons (sizeof(struct TransportSynMessage));
1958  connect_msg.reserved = htonl (0);
1960  if (-1 ==
1961  papi->send (papi->cls,
1962  na->session,
1963  (const char *) &connect_msg,
1964  sizeof(struct TransportSynMessage),
1965  UINT_MAX,
1967  &send_session_syn_cont, NULL))
1968  {
1970  _ ("Failed to transmit SYN message to %s\n"),
1971  GST_plugins_a2s (na->address));
1972  n = lookup_neighbour (&na->address->peer);
1973  if (NULL == n)
1974  {
1975  GNUNET_break (0);
1976  return;
1977  }
1978  switch (n->state)
1979  {
1981  /* Remove address and request and additional one */
1982  GNUNET_assert (na == &n->primary_address);
1988  /* Hard failure to send the SYN message with this address:
1989  Destroy address and session */
1990  break;
1991 
1993  /* Remove address and request an additional one */
1994  GNUNET_assert (na == &n->primary_address);
2000  break;
2001 
2003  GNUNET_assert (na == &n->alternative_address);
2005  gettext_noop (
2006  "# Failed attempts to switch addresses (failed to send SYN)"),
2007  1,
2008  GNUNET_NO);
2009  /* Remove address and request an additional one */
2011  "Switch failed, cleaning up alternative address\n");
2017  break;
2018 
2019  default:
2020  GNUNET_break (0);
2022  break;
2023  }
2024  return;
2025  }
2027  na->session,
2028  sizeof(struct TransportSynMessage));
2029 }
2030 
2031 
2044 static void
2046  const struct GNUNET_PeerIdentity *target,
2047  int result,
2048  size_t size_payload,
2049  size_t size_on_wire)
2050 {
2051  struct NeighbourMapEntry *n;
2052 
2053  (void) cls;
2054  (void) size_payload;
2055  (void) size_on_wire;
2056  n = lookup_neighbour (target);
2057  if (NULL == n)
2058  {
2059  /* SYN_ACK continuation was called after neighbor was freed,
2060  * for example due to a time out for the state or the session
2061  * used was already terminated: nothing to do here... */
2062  return;
2063  }
2064 
2066  {
2067  /* SYN_ACK continuation was called after neighbor changed state,
2068  * for example due to a time out for the state or the session
2069  * used was already terminated: nothing to do here... */
2070  return;
2071  }
2072  if (GNUNET_OK == result)
2073  return;
2074 
2076  _ (
2077  "Failed to send SYN_ACK message to peer `%s' using address `%s'\n"),
2078  GNUNET_i2s (target),
2080 
2081  /* Remove address and request and additional one */
2082  /* FIXME: what if the neighbour's primary address
2083  changed in the meantime? Might want to instead
2084  pass "something" around in closure to be sure. */
2091 }
2092 
2093 
2101 static void
2103  struct GNUNET_TIME_Absolute timestamp)
2104 {
2105  const struct GNUNET_HELLO_Address *address = na->address;
2106  struct GNUNET_ATS_Session *session = na->session;
2107  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2108  struct TransportSynMessage connect_msg;
2109  struct NeighbourMapEntry *n;
2110 
2112  "Sending SYN_ACK to peer `%s'\n",
2113  GNUNET_i2s (&address->peer));
2114 
2115  if (NULL == (papi = GST_plugins_find (address->transport_name)))
2116  {
2117  GNUNET_break (0);
2118  return;
2119  }
2120  if (NULL == session)
2121  session = papi->get_session (papi->cls,
2122  address);
2123  if (NULL == session)
2124  {
2125  GNUNET_break (0);
2126  return;
2127  }
2129  session);
2131  gettext_noop
2132  ("# SYN_ACK messages sent"),
2133  1, GNUNET_NO);
2134  connect_msg.header.size = htons (sizeof(struct TransportSynMessage));
2135  connect_msg.header.type = htons (
2137  connect_msg.reserved = htonl (0);
2138  connect_msg.timestamp = GNUNET_TIME_absolute_hton (timestamp);
2139 
2140  if (GNUNET_SYSERR ==
2141  papi->send (papi->cls,
2142  session,
2143  (const char *) &connect_msg,
2144  sizeof(struct TransportSynMessage),
2145  UINT_MAX,
2147  &send_session_syn_ack_cont, NULL))
2148  {
2150  _ ("Failed to transmit SYN_ACK message to %s\n"),
2152 
2153  n = lookup_neighbour (&address->peer);
2154  if (NULL == n)
2155  {
2156  GNUNET_break (0);
2157  return;
2158  }
2159  /* Remove address and request and additional one */
2166  return;
2167  }
2168 }
2169 
2170 
2179 static void
2181 {
2182  struct NeighbourMapEntry *n = cls;
2183  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2184  struct GNUNET_TIME_Relative delay;
2185  int do_forward;
2186 
2187  if (NULL == n->primary_address.address)
2188  return; /* not active, ignore */
2190  GNUNET_assert (NULL != papi);
2191  if (NULL == papi->update_inbound_delay)
2192  return;
2194  0,
2195  &do_forward);
2197  "New inbound delay for peer `%s' is %llu ms\n",
2198  GNUNET_i2s (&n->id),
2199  (unsigned long long) delay.rel_value_us / 1000LL);
2200  if (NULL == n->primary_address.session)
2201  return;
2202  papi->update_inbound_delay (papi->cls,
2203  &n->id,
2205  delay);
2206 }
2207 
2208 
2215 static struct NeighbourMapEntry *
2217 {
2218  struct NeighbourMapEntry *n;
2219 
2220  if (0 ==
2221  memcmp (&GST_my_identity,
2222  peer,
2223  sizeof(struct GNUNET_PeerIdentity)))
2224  {
2226  "Cowardly refusing to consider myself my neighbour!\n");
2227  return NULL;
2228  }
2230  "Creating new neighbour entry for `%s'\n",
2231  GNUNET_i2s (peer));
2232  n = GNUNET_new (struct NeighbourMapEntry);
2233  n->id = *peer;
2234  n->ack_state = ACK_UNDEFINED;
2239  n,
2248  &n->id,
2249  n,
2252  peer,
2253  0);
2254 
2255  return n;
2256 }
2257 
2258 
2263 {
2268 
2273 
2278 
2283 
2288 };
2289 
2290 
2299 int
2301  const struct GNUNET_PeerIdentity *peer)
2302 {
2303  const struct TransportSynMessage *scm;
2304  struct NeighbourMapEntry *n;
2305  struct GNUNET_TIME_Absolute ts;
2306 
2307  if (ntohs (message->size) != sizeof(struct TransportSynMessage))
2308  {
2309  GNUNET_break_op (0);
2310  return GNUNET_SYSERR;
2311  }
2313  gettext_noop
2314  ("# SYN messages received"),
2315  1, GNUNET_NO);
2316  if (NULL == neighbours)
2317  {
2319  _ (
2320  "SYN request from peer `%s' ignored due impending shutdown\n"),
2321  GNUNET_i2s (peer));
2322  return GNUNET_OK; /* we're shutting down */
2323  }
2324  scm = (const struct TransportSynMessage *) message;
2325  GNUNET_break_op (0 == ntohl (scm->reserved));
2327  if (0 ==
2328  memcmp (&GST_my_identity,
2329  peer,
2330  sizeof(struct GNUNET_PeerIdentity)))
2331  {
2332  /* loopback connection-to-self, ignore */
2333  return GNUNET_SYSERR;
2334  }
2335  n = lookup_neighbour (peer);
2336  if (NULL == n)
2337  {
2338  /* This is a new neighbour and set to not connected */
2339  n = setup_neighbour (peer);
2340  GNUNET_assert (NULL != n);
2341  }
2342 
2343  /* Remember this SYN message in neighbour */
2345  n->connect_ack_timestamp = ts;
2346 
2348  "Received SYN for peer `%s' in state %s/%s\n",
2349  GNUNET_i2s (peer),
2351  print_ack_state (n->ack_state));
2352 
2353  switch (n->state)
2354  {
2356  /* Request an address from ATS to send SYN_ACK to this peer */
2361  break;
2362 
2364  /* SYN message takes priority over us asking ATS for address:
2365  * Wait for ATS to suggest an address and send SYN_ACK */
2370  break;
2371 
2373  /* We already wait for an address to send an SYN_ACK */
2374  break;
2375 
2378  /* Send ACK immediately */
2379  n->ack_state = ACK_SEND_ACK;
2381  ts);
2382  break;
2383 
2385  /* we are already connected and can thus send the ACK immediately */
2386  GNUNET_assert (NULL != n->primary_address.address);
2387  GNUNET_assert (NULL != n->primary_address.session);
2388  n->ack_state = ACK_SEND_ACK;
2390  ts);
2391  break;
2392 
2394  /* We wait for ATS address suggestion */
2395  break;
2396 
2398  /* We received a SYN message while waiting for a SYN_ACK in fast
2399  * reconnect. Send SYN_ACK immediately */
2400  n->ack_state = ACK_SEND_ACK;
2403  break;
2404 
2406  /* We are already connected and can thus send the ACK immediately;
2407  still, it can never hurt to have an alternative address, so also
2408  tell ATS about it */
2409  GNUNET_assert (NULL != n->primary_address.address);
2410  GNUNET_assert (NULL != n->primary_address.session);
2411  n->ack_state = ACK_SEND_ACK;
2413  ts);
2414  break;
2415 
2417  /* Get rid of remains and re-try */
2418  free_neighbour (n);
2419  n = setup_neighbour (peer);
2420  GNUNET_assert (NULL != n);
2421  /* Remember the SYN time stamp for ACK message */
2423  n->connect_ack_timestamp = ts;
2424  /* Request an address for the peer */
2429  break;
2430 
2432  /* should not be possible */
2433  GNUNET_assert (0);
2434  break;
2435 
2436  default:
2438  "Unhandled state `%s'\n",
2440  GNUNET_break (0);
2441  return GNUNET_SYSERR;
2442  }
2443  return GNUNET_OK;
2444 }
2445 
2446 
2463 static int
2465  struct GNUNET_ATS_Session *session,
2466  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
2467  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
2468 {
2469  struct NeighbourMapEntry *n;
2470 
2471  n = lookup_neighbour (&address->peer);
2472  if ((NULL == n) ||
2473  (NULL == n->primary_address.address) ||
2475  n->primary_address.address)))
2476  return GNUNET_NO;
2477  /* We are not really switching addresses, but merely adjusting
2478  session and/or bandwidth, can do fast ATS update! */
2479  if (session != n->primary_address.session)
2480  {
2481  /* switch to a different session, but keeping same address; could
2482  happen if there is a 2nd inbound connection */
2483  n->primary_address.session = session;
2486  n->primary_address.session));
2487  }
2488  if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__)
2489  {
2490  n->primary_address.bandwidth_in = bandwidth_in;
2491  if (GNUNET_YES !=
2492  set_incoming_quota (n,
2493  bandwidth_in))
2494  return GNUNET_NO;
2495  }
2496  if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__)
2497  {
2498  n->primary_address.bandwidth_out = bandwidth_out;
2500  }
2501  return GNUNET_OK;
2502 }
2503 
2504 
2518 static void
2520  const struct GNUNET_PeerIdentity *peer,
2521  const struct GNUNET_HELLO_Address *address,
2522  struct GNUNET_ATS_Session *session,
2523  int result)
2524 {
2525  struct BlacklistCheckSwitchContext *blc_ctx = cls;
2526  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2527  struct NeighbourMapEntry *n;
2528 
2529  if (GNUNET_SYSERR == result)
2530  goto cleanup;
2531 
2532  papi = GST_plugins_find (address->transport_name);
2533  if (NULL == papi)
2534  {
2535  /* This can happen during shutdown. */
2536  goto cleanup;
2537  }
2538 
2539  if (GNUNET_NO == result)
2540  {
2542  "Blacklist denied to switch to suggested address `%s' session %p for peer `%s'\n",
2544  session,
2545  GNUNET_i2s (peer));
2547  "# ATS suggestions ignored (blacklist denied)",
2548  1,
2549  GNUNET_NO);
2550  if (NULL != session)
2551  papi->disconnect_session (papi->cls,
2552  session);
2553  if (GNUNET_YES !=
2557  NULL);
2558  goto cleanup;
2559  }
2560 
2561 
2562  if (NULL == session)
2563  {
2564  /* need to create a session, ATS only gave us an address */
2565  session = papi->get_session (papi->cls,
2566  address);
2568  "Obtained new session for peer `%s' and address '%s': %p\n",
2569  GNUNET_i2s (&address->peer),
2571  session);
2572  if (NULL != session)
2574  session);
2575  }
2576  if (NULL == session)
2577  {
2578  /* session creation failed, bad!, fail! */
2580  "# ATS suggestions ignored (failed to create session)",
2581  1,
2582  GNUNET_NO);
2583  /* No session could be obtained, remove blacklist check and clean up */
2585  "Failed to obtain new session for peer `%s' and address '%s'\n",
2586  GNUNET_i2s (&address->peer),
2589  session);
2590  goto cleanup;
2591  }
2592 
2593  /* We did this check already before going into blacklist, but
2594  it is theoretically possible that the situation changed in
2595  the meantime, hence we check again here */
2596  if (GNUNET_OK ==
2598  session,
2599  blc_ctx->bandwidth_in,
2600  blc_ctx->bandwidth_out))
2601  goto cleanup; /* was just a minor update, we're done */
2602 
2603  /* check if we also need to setup the neighbour entry */
2604  if (NULL == (n = lookup_neighbour (peer)))
2605  {
2606  n = setup_neighbour (peer);
2607  if (NULL == n)
2608  {
2609  /* not sure how this can happen... */
2610  GNUNET_break (0);
2611  goto cleanup;
2612  }
2614  }
2615 
2617  "Peer `%s' switches to address `%s'\n",
2618  GNUNET_i2s (&address->peer),
2620 
2621  switch (n->state)
2622  {
2624  GNUNET_break (0);
2626  session);
2627  free_neighbour (n);
2628  return;
2629 
2631  /* We requested an address and ATS suggests one:
2632  * set primary address and send SYN message*/
2634  address,
2635  session,
2636  blc_ctx->bandwidth_in,
2637  blc_ctx->bandwidth_out);
2638  if (ACK_SEND_SYN_ACK == n->ack_state)
2639  {
2640  /* Send pending SYN_ACK message */
2641  n->ack_state = ACK_SEND_ACK;
2644  }
2649  send_syn (&n->primary_address);
2650  break;
2651 
2653  /* ATS suggested a new address while waiting for an SYN_ACK:
2654  * Switch and send new SYN */
2655  /* ATS suggests a different address, switch again */
2657  address,
2658  session,
2659  blc_ctx->bandwidth_in,
2660  blc_ctx->bandwidth_out);
2661  if (ACK_SEND_SYN_ACK == n->ack_state)
2662  {
2663  /* Send pending SYN_ACK message */
2664  n->ack_state = ACK_SEND_ACK;
2667  }
2672  send_syn (&n->primary_address);
2673  break;
2674 
2676  /* We requested an address and ATS suggests one:
2677  * set primary address and send SYN_ACK message*/
2679  address,
2680  session,
2681  blc_ctx->bandwidth_in,
2682  blc_ctx->bandwidth_out);
2683  /* Send an ACK message as a response to the SYN msg */
2690  if ((ACK_SEND_SYN_ACK == n->ack_state) ||
2691  (ACK_UNDEFINED == n->ack_state))
2692  n->ack_state = ACK_SEND_ACK;
2693  break;
2694 
2696  /* ATS asks us to switch while we were trying to connect; switch to new
2697  address and check blacklist again */
2698  if ((ACK_SEND_SYN_ACK == n->ack_state))
2699  {
2700  n->ack_state = ACK_SEND_ACK;
2703  }
2705  address,
2706  session,
2707  blc_ctx->bandwidth_in,
2708  blc_ctx->bandwidth_out);
2713  break;
2714 
2716  GNUNET_assert (NULL != n->primary_address.address);
2717  GNUNET_assert (NULL != n->primary_address.session);
2718  GNUNET_break (n->primary_address.session != session);
2719  /* ATS asks us to switch a life connection; see if we can get
2720  a SYN_ACK on it before we actually do this! */
2722  address,
2723  session,
2724  blc_ctx->bandwidth_in,
2725  blc_ctx->bandwidth_out);
2731  gettext_noop ("# Attempts to switch addresses"),
2732  1,
2733  GNUNET_NO);
2735  break;
2736 
2739  address,
2740  session,
2741  blc_ctx->bandwidth_in,
2742  blc_ctx->bandwidth_out);
2743  if (ACK_SEND_SYN_ACK == n->ack_state)
2744  {
2745  /* Send pending SYN_ACK message */
2746  n->ack_state = ACK_SEND_ACK;
2749  }
2754  send_syn (&n->primary_address);
2755  break;
2756 
2758  /* ATS asks us to switch while we were trying to reconnect; switch to new
2759  address and send SYN again */
2761  address,
2762  session,
2763  blc_ctx->bandwidth_in,
2764  blc_ctx->bandwidth_out);
2769  send_syn (&n->primary_address);
2770  break;
2771 
2774  address)) &&
2775  (n->primary_address.session == session))
2776  {
2777  /* ATS switches back to still-active session */
2779  "ATS double-switched, cleaning up alternative address\n");
2783  n->timeout);
2784  break;
2785  }
2786  /* ATS asks us to switch a life connection, send */
2788  address,
2789  session,
2790  blc_ctx->bandwidth_in,
2791  blc_ctx->bandwidth_out);
2797  break;
2798 
2800  /* not going to switch addresses while disconnecting */
2802  "# ATS suggestion ignored (disconnecting)",
2803  1,
2804  GNUNET_NO);
2805  return;
2806 
2808  GNUNET_assert (0);
2809  break;
2810 
2811  default:
2813  "Unhandled state `%s'\n",
2815  GNUNET_break (0);
2816  break;
2817  }
2818 cleanup:
2821  blc_ctx);
2822  GNUNET_free (blc_ctx);
2823 }
2824 
2825 
2843 void
2845  struct GNUNET_ATS_Session *session,
2847  bandwidth_in,
2849  bandwidth_out)
2850 {
2851  struct GST_BlacklistCheck *blc;
2852  struct BlacklistCheckSwitchContext *blc_ctx;
2853 
2854  GNUNET_assert (NULL != address->transport_name);
2855  if (GNUNET_OK ==
2857  session,
2858  bandwidth_in,
2859  bandwidth_out))
2860  return;
2861 
2862  /* Check if plugin is available */
2863  if (NULL == (GST_plugins_find (address->transport_name)))
2864  {
2865  /* we don't have the plugin for this address */
2866  GNUNET_break (0);
2868  session);
2869  return;
2870  }
2871  if ((NULL == session) &&
2874  {
2875  /* This is a inbound address and we do not have a session to use! */
2876  GNUNET_break (0);
2878  session);
2879  return;
2880  }
2881 
2883  "ATS suggests address '%s' for peer `%s' at %u/%u speed\n",
2885  GNUNET_i2s (&address->peer),
2886  (unsigned int) ntohl (bandwidth_in.value__),
2887  (unsigned int) ntohl (bandwidth_out.value__));
2888 
2889  /* Perform blacklist check */
2890  blc_ctx = GNUNET_new (struct BlacklistCheckSwitchContext);
2891  blc_ctx->bandwidth_in = bandwidth_in;
2892  blc_ctx->bandwidth_out = bandwidth_out;
2895  blc_ctx);
2896  if (NULL != (blc = GST_blacklist_test_allowed (&address->peer,
2897  address->transport_name,
2899  blc_ctx,
2900  address,
2901  session)))
2902  {
2903  blc_ctx->blc = blc;
2904  }
2905 }
2906 
2907 
2917 static int
2919  const struct GNUNET_PeerIdentity *key,
2920  void *value)
2921 {
2922  struct NeighbourMapEntry *n = value;
2923  uint32_t bps_in;
2924  uint32_t bps_out;
2925  struct GNUNET_TIME_Relative delta;
2926 
2927  (void) cls;
2928  if ((GNUNET_YES != test_connected (n)) ||
2929  (NULL == n->primary_address.address))
2930  return GNUNET_OK;
2933  bps_in = 0;
2934  if ((0 != n->util_total_bytes_recv) && (0 != delta.rel_value_us))
2935  bps_in = (1000LL * 1000LL * n->util_total_bytes_recv)
2936  / (delta.rel_value_us);
2937  bps_out = 0;
2938  if ((0 != n->util_total_bytes_sent) && (0 != delta.rel_value_us))
2939  bps_out = (1000LL * 1000LL * n->util_total_bytes_sent) / delta.rel_value_us;
2940 
2942  "`%s' total: received %u Bytes/s, sent %u Bytes/s\n",
2943  GNUNET_i2s (key),
2944  bps_in,
2945  bps_out);
2947  bps_in,
2948  bps_out);
2949  n->util_total_bytes_recv = 0;
2950  n->util_total_bytes_sent = 0;
2952  return GNUNET_OK;
2953 }
2954 
2955 
2961 static void
2963 {
2964  (void) cls;
2965  util_transmission_tk = NULL;
2968  NULL);
2972  NULL);
2973 }
2974 
2975 
2984 void
2986  const struct GNUNET_MessageHeader *message)
2987 {
2988  struct NeighbourMapEntry *n;
2989 
2990  n = lookup_neighbour (&address->peer);
2991  if (NULL == n)
2992  return;
2993  n->util_total_bytes_recv += ntohs (message->size);
2994 }
2995 
2996 
3006 void
3008  struct GNUNET_ATS_Session *session,
3009  size_t size)
3010 {
3011  struct NeighbourMapEntry *n;
3012 
3013  n = lookup_neighbour (&address->peer);
3014  if (NULL == n)
3015  return;
3016  if (n->primary_address.session != session)
3017  return;
3019 }
3020 
3021 
3029 static void
3030 master_task (void *cls)
3031 {
3032  struct NeighbourMapEntry *n = cls;
3033  struct GNUNET_TIME_Relative delay;
3034 
3035  n->task = NULL;
3038  "Master task runs for neighbour `%s' in state %s with timeout in %s\n",
3039  GNUNET_i2s (&n->id),
3042  GNUNET_YES));
3043  switch (n->state)
3044  {
3046  /* invalid state for master task, clean up */
3047  GNUNET_break (0);
3048  free_neighbour (n);
3049  return;
3050 
3052  if (0 == delay.rel_value_us)
3053  {
3055  "Connection to `%s' timed out waiting for ATS to provide address\n",
3056  GNUNET_i2s (&n->id));
3057  free_neighbour (n);
3058  return;
3059  }
3060  break;
3061 
3063  if (0 == delay.rel_value_us)
3064  {
3066  "Connection to `%s' timed out waiting for other peer to send SYN_ACK\n",
3067  GNUNET_i2s (&n->id));
3068  /* Remove address and request and additional one */
3074  return;
3075  }
3076  break;
3077 
3079  if (0 == delay.rel_value_us)
3080  {
3082  "Connection to `%s' timed out waiting ATS to provide address to use for SYN_ACK\n",
3083  GNUNET_i2s (&n->id));
3084  free_neighbour (n);
3085  return;
3086  }
3087  break;
3088 
3090  if (0 == delay.rel_value_us)
3091  {
3093  "Connection to `%s' timed out waiting for other peer to send ACK\n",
3094  GNUNET_i2s (&n->id));
3096  return;
3097  }
3098  break;
3099 
3101  if (0 == delay.rel_value_us)
3102  {
3104  "Connection to `%s' timed out, missing KEEPALIVE_RESPONSEs\n",
3105  GNUNET_i2s (&n->id));
3107  return;
3108  }
3110  send_keepalive (n);
3111  break;
3112 
3114  if (0 == delay.rel_value_us)
3115  {
3117  "Connection to `%s' timed out, waiting for ATS replacement address\n",
3118  GNUNET_i2s (&n->id));
3120  return;
3121  }
3122  break;
3123 
3125  if (0 == delay.rel_value_us)
3126  {
3128  "Connection to `%s' timed out, waiting for other peer to SYN_ACK replacement address\n",
3129  GNUNET_i2s (&n->id));
3131  return;
3132  }
3133  break;
3134 
3136  if (0 == delay.rel_value_us)
3137  {
3139  "Switch failed, cleaning up alternative address\n");
3145  }
3147  send_keepalive (n);
3148  break;
3149 
3152  "Cleaning up connection to `%s' after sending DISCONNECT\n",
3153  GNUNET_i2s (&n->id));
3154  free_neighbour (n);
3155  return;
3156 
3158  /* how did we get here!? */
3159  GNUNET_assert (0);
3160  break;
3161 
3162  default:
3164  "Unhandled state `%s'\n",
3166  GNUNET_break (0);
3167  break;
3168  }
3172  {
3173  /* if we are *now* in one of the two states, we're sending
3174  keep alive messages, so we need to consider the keepalive
3175  delay, not just the connection timeout */
3177  n->keep_alive_time),
3178  delay);
3179  }
3180  if (NULL == n->task)
3182  &master_task,
3183  n);
3184 }
3185 
3186 
3193 static void
3195 {
3196  struct GNUNET_MessageHeader msg;
3197 
3199  "Sending ACK message to peer `%s'\n",
3200  GNUNET_i2s (&n->id));
3201 
3202  msg.size = htons (sizeof(struct GNUNET_MessageHeader));
3204  (void) send_with_session (n,
3205  &msg,
3206  sizeof(struct GNUNET_MessageHeader),
3207  UINT32_MAX,
3209  GNUNET_NO,
3210  NULL, NULL);
3211 }
3212 
3213 
3225 int
3227  GNUNET_MessageHeader *message,
3228  const struct
3230  struct GNUNET_ATS_Session *session)
3231 {
3232  const struct TransportSynMessage *scm;
3233  struct GNUNET_TIME_Absolute ts;
3234  struct NeighbourMapEntry *n;
3235 
3236  (void) session;
3237  if (ntohs (message->size) != sizeof(struct TransportSynMessage))
3238  {
3239  GNUNET_break_op (0);
3240  return GNUNET_SYSERR;
3241  }
3243  gettext_noop
3244  ("# SYN_ACK messages received"),
3245  1, GNUNET_NO);
3246  scm = (const struct TransportSynMessage *) message;
3247  GNUNET_break_op (ntohl (scm->reserved) == 0);
3248  if (NULL == (n = lookup_neighbour (&address->peer)))
3249  {
3251  gettext_noop
3252  ("# unexpected SYN_ACK messages (no peer)"),
3253  1, GNUNET_NO);
3254  return GNUNET_SYSERR;
3255  }
3257  "Received SYN_ACK message from peer `%s' in state %s/%s\n",
3258  GNUNET_i2s (&address->peer),
3260  print_ack_state (n->ack_state));
3262  switch (n->state)
3263  {
3265  GNUNET_break (0);
3266  free_neighbour (n);
3267  return GNUNET_SYSERR;
3268 
3271  gettext_noop (
3272  "# unexpected SYN_ACK messages (not ready)"),
3273  1,
3274  GNUNET_NO);
3275  break;
3276 
3279  {
3281  "SYN_ACK ignored as the timestamp does not match our SYN request\n");
3282  return GNUNET_OK;
3283  }
3294  break;
3295 
3299  gettext_noop (
3300  "# unexpected SYN_ACK messages (not ready)"),
3301  1,
3302  GNUNET_NO);
3303  break;
3304 
3306  /* duplicate SYN_ACK, let's answer by duplicate ACK just in case */
3308  break;
3309 
3311  /* we didn't expect any SYN_ACK, as we are waiting for ATS
3312  to give us a new address... */
3314  gettext_noop (
3315  "# unexpected SYN_ACK messages (waiting on ATS)"),
3316  1,
3317  GNUNET_NO);
3318  break;
3319 
3321  /* Reconnecting with new address address worked; go back to connected! */
3327  break;
3328 
3330  /* new address worked; adopt it and go back to connected! */
3336 
3337  /* Set primary addresses */
3344  gettext_noop (
3345  "# Successful attempts to switch addresses"),
3346  1,
3347  GNUNET_NO);
3348 
3350  memset (&n->alternative_address,
3351  0,
3352  sizeof(n->alternative_address));
3354  break;
3355 
3358  gettext_noop
3359  ("# unexpected SYN_ACK messages (disconnecting)"),
3360  1, GNUNET_NO);
3361  return GNUNET_SYSERR;
3362 
3364  GNUNET_assert (0);
3365  break;
3366 
3367  default:
3369  "Unhandled state `%s'\n",
3371  GNUNET_break (0);
3372  return GNUNET_SYSERR;
3373  }
3374  return GNUNET_OK;
3375 }
3376 
3377 
3387 int
3389  struct GNUNET_ATS_Session *session)
3390 {
3391  struct NeighbourMapEntry *n;
3392 
3393  if (NULL == (n = lookup_neighbour (peer)))
3394  return GNUNET_NO; /* can't affect us */
3395  if (session != n->primary_address.session)
3396  {
3397  /* Free alternative address */
3398  if (session == n->alternative_address.session)
3399  {
3403  n->timeout);
3405  "Session died, cleaning up alternative address\n");
3407  }
3408  return GNUNET_NO; /* doesn't affect us further */
3409  }
3410 
3412  /* The session for neighbour's primary address died */
3413  switch (n->state)
3414  {
3416  GNUNET_break (0);
3417  free_neighbour (n);
3418  return GNUNET_YES;
3419 
3421  GNUNET_break (0);
3422  free_neighbour (n);
3423  return GNUNET_YES;
3424 
3426  /* The session used to send the SYN terminated:
3427  * this implies a connect error*/
3429  "Failed to send SYN in CONNECT_SENT with `%s' %p: session terminated\n",
3432 
3433  /* Destroy the address since it cannot be used */
3439  break;
3440 
3443  /* error on inbound session; free neighbour entirely */
3444  free_neighbour (n);
3445  return GNUNET_YES;
3446 
3448  /* Our primary connection died, try a fast reconnect */
3454  break;
3455 
3457  /* we don't have an address, how can it go down? */
3458  GNUNET_break (0);
3459  break;
3460 
3463  "Failed to send SYN in RECONNECT_SENT with `%s' %p: session terminated\n",
3466  /* Destroy the address since it cannot be used */
3472  break;
3473 
3475  /* primary went down while we were waiting for SYN_ACK on secondary;
3476  secondary as primary */
3477 
3479  "Connection `%s' %p to peer `%s' was terminated while switching, "
3480  "switching to alternative address `%s' %p\n",
3483  GNUNET_i2s (peer),
3486 
3487  /* Destroy the inbound address since it cannot be used */
3492  n->primary_address.session));
3493  memset (&n->alternative_address,
3494  0,
3495  sizeof(struct NeighbourAddress));
3500  break;
3501 
3504  break;
3505 
3507  /* neighbour was freed and plugins told to terminate session */
3508  return GNUNET_NO;
3509 
3510  default:
3512  "Unhandled state `%s'\n",
3514  GNUNET_break (0);
3515  break;
3516  }
3517  if (NULL != n->task)
3520  return GNUNET_YES;
3521 }
3522 
3523 
3534 int
3536  const struct GNUNET_HELLO_Address *address,
3537  struct GNUNET_ATS_Session *session)
3538 {
3539  struct NeighbourMapEntry *n;
3540 
3541  (void) session;
3542  if (ntohs (message->size) != sizeof(struct GNUNET_MessageHeader))
3543  {
3544  GNUNET_break_op (0);
3545  return GNUNET_SYSERR;
3546  }
3548  gettext_noop ("# ACK messages received"),
3549  1,
3550  GNUNET_NO);
3551  if (NULL == (n = lookup_neighbour (&address->peer)))
3552  {
3553  GNUNET_break_op (0);
3554  return GNUNET_SYSERR;
3555  }
3557  "Received ACK for peer `%s' in state %s/%s\n",
3558  GNUNET_i2s (&address->peer),
3560  print_ack_state (n->ack_state));
3561 
3562  /* Check if we are in a plausible state for having sent
3563  a SYN_ACK. If not, return, otherwise break.
3564 
3565  The remote peers sends a ACK as a response for a SYN_ACK
3566  message.
3567 
3568  We expect a ACK:
3569  - If a remote peer has sent a SYN, we responded with a SYN_ACK and
3570  now wait for the ACK to finally be connected
3571  - If we sent a SYN_ACK to this peer before */if (((GNUNET_TRANSPORT_PS_SYN_RECV_ACK != n->state) &&
3572  (ACK_SEND_ACK != n->ack_state)) ||
3573  (NULL == n->primary_address.address))
3574  {
3576  "Received unexpected ACK message from peer `%s' in state %s/%s\n",
3577  GNUNET_i2s (&address->peer),
3579  print_ack_state (n->ack_state));
3580 
3582  gettext_noop ("# unexpected ACK messages"),
3583  1,
3584  GNUNET_NO);
3585  return GNUNET_OK;
3586  }
3588  {
3589  /* We tried to switch addresses while being connect. We explicitly wait
3590  * for a SYN_ACK before going to GNUNET_TRANSPORT_PS_CONNECTED,
3591  * so we do not want to set the address as in use! */
3592  return GNUNET_OK;
3593  }
3598 
3599  if (NULL == n->primary_address.address)
3600  {
3601  /* See issue #3693.
3602  * We are in state = PSY_SYN_RECV_ACK or ack_state = ACK_SEND_ACK, which
3603  * really means we did try (and succeed) to send a SYN and are waiting for
3604  * an ACK.
3605  * That suggests that the primary_address used to be non-NULL, but maybe it
3606  * got reset to NULL without the state being changed appropriately?
3607  */GNUNET_break (0);
3608  return GNUNET_OK;
3609  }
3610 
3611  /* Reset backoff for primary address */
3614  return GNUNET_OK;
3615 }
3616 
3617 
3624 int
3626 {
3627  return test_connected (lookup_neighbour (target));
3628 }
3629 
3630 
3636 static void
3638 {
3639  struct NeighbourMapEntry *n = cls;
3640 
3641  n->delayed_disconnect_task = NULL;
3643  "Disconnecting by request from peer %s\n",
3644  GNUNET_i2s (&n->id));
3645  free_neighbour (n);
3646 }
3647 
3648 
3656 void
3658  const struct GNUNET_MessageHeader *msg)
3659 {
3660  struct NeighbourMapEntry *n;
3661  const struct GNUNET_ATS_SessionQuotaMessage *sqm;
3662  struct GNUNET_BANDWIDTH_Value32NBO last;
3663 
3665  "Received QUOTA message from peer `%s'\n",
3666  GNUNET_i2s (peer));
3667  if (ntohs (msg->size) != sizeof(struct GNUNET_ATS_SessionQuotaMessage))
3668  {
3669  GNUNET_break_op (0);
3671  gettext_noop (
3672  "# quota messages ignored (malformed)"),
3673  1,
3674  GNUNET_NO);
3675  return;
3676  }
3678  gettext_noop
3679  ("# QUOTA messages received"),
3680  1, GNUNET_NO);
3681  sqm = (const struct GNUNET_ATS_SessionQuotaMessage *) msg;
3682  if (NULL == (n = lookup_neighbour (peer)))
3683  {
3684  /* gone already */
3685  return;
3686  }
3689  sqm->quota)));
3690  if (last.value__ != n->neighbour_receive_quota.value__)
3691  {
3692  n->neighbour_receive_quota = last;
3694  }
3695 }
3696 
3697 
3705 void
3708  const struct
3710 {
3711  struct NeighbourMapEntry *n;
3712  const struct GNUNET_ATS_SessionDisconnectMessage *sdm;
3713 
3715  "Received DISCONNECT message from peer `%s'\n",
3716  GNUNET_i2s (peer));
3717  if (ntohs (msg->size) != sizeof(struct GNUNET_ATS_SessionDisconnectMessage))
3718  {
3719  GNUNET_break_op (0);
3721  gettext_noop
3722  ("# disconnect messages ignored (malformed)"),
3723  1,
3724  GNUNET_NO);
3725  return;
3726  }
3728  gettext_noop
3729  ("# DISCONNECT messages received"),
3730  1, GNUNET_NO);
3731  sdm = (const struct GNUNET_ATS_SessionDisconnectMessage *) msg;
3732  if (NULL == (n = lookup_neighbour (peer)))
3733  {
3734  /* gone already */
3735  return;
3736  }
3739  {
3741  gettext_noop (
3742  "# disconnect messages ignored (timestamp)"),
3743  1,
3744  GNUNET_NO);
3745  return;
3746  }
3747  if (0 != memcmp (peer,
3748  &sdm->public_key,
3749  sizeof(struct GNUNET_PeerIdentity)))
3750  {
3751  GNUNET_break_op (0);
3752  return;
3753  }
3754  if (ntohl (sdm->purpose.size) !=
3755  sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
3756  + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
3757  + sizeof(struct GNUNET_TIME_AbsoluteNBO))
3758  {
3760  "DISCONNECT message from peer `%s' has invalid size\n",
3761  GNUNET_i2s (peer));
3762  GNUNET_break_op (0);
3763  return;
3764  }
3765  if (GNUNET_OK !=
3768  &sdm->purpose,
3769  &sdm->signature,
3770  &sdm->public_key))
3771  {
3773  "DISCONNECT message from peer `%s' cannot be verified \n",
3774  GNUNET_i2s (peer));
3775  GNUNET_break_op (0);
3776  return;
3777  }
3778  if (NULL == n->delayed_disconnect_task)
3779  {
3781  n);
3782  }
3783 }
3784 
3785 
3790 {
3795 
3799  void *cb_cls;
3800 };
3801 
3802 
3811 static int
3813  const struct GNUNET_PeerIdentity *key,
3814  void *value)
3815 {
3816  struct IteratorContext *ic = cls;
3817  struct NeighbourMapEntry *n = value;
3818  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
3819  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
3820 
3821  (void) key;
3822  if (NULL != n->primary_address.address)
3823  {
3824  bandwidth_in = n->primary_address.bandwidth_in;
3825  bandwidth_out = n->primary_address.bandwidth_out;
3826  }
3827  else
3828  {
3829  bandwidth_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
3830  bandwidth_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
3831  }
3832  ic->cb (ic->cb_cls,
3833  &n->id,
3835  n->state,
3836  n->timeout,
3837  bandwidth_in, bandwidth_out);
3838  return GNUNET_OK;
3839 }
3840 
3841 
3848 void
3850  void *cb_cls)
3851 {
3852  struct IteratorContext ic;
3853 
3854  if (NULL == neighbours)
3855  return; /* can happen during shutdown */
3856  ic.cb = cb;
3857  ic.cb_cls = cb_cls;
3860  &ic);
3861 }
3862 
3863 
3869 void
3871 {
3872  struct NeighbourMapEntry *n;
3873 
3874  if (NULL == (n = lookup_neighbour (target)))
3875  return; /* not active */
3876  if (GNUNET_YES == test_connected (n))
3878  gettext_noop (
3879  "# disconnected from peer upon explicit request"),
3880  1,
3881  GNUNET_NO);
3883  "Forced disconnect from peer %s\n",
3884  GNUNET_i2s (target));
3886 }
3887 
3888 
3895 const struct GNUNET_HELLO_Address *
3897 {
3898  struct NeighbourMapEntry *n;
3899 
3900  n = lookup_neighbour (peer);
3901  if (NULL == n)
3902  return NULL;
3903  return n->primary_address.address;
3904 }
3905 
3906 
3912 void
3913 GST_neighbours_start (unsigned int max_fds)
3914 {
3915  (void) max_fds;
3917  GNUNET_NO);
3921  NULL);
3922 }
3923 
3924 
3933 static int
3935  const struct GNUNET_PeerIdentity *key,
3936  void *value)
3937 {
3938  struct NeighbourMapEntry *n = value;
3939 
3940  (void) cls;
3941  (void) key;
3943  "Disconnecting peer `%4s' during shutdown\n",
3944  GNUNET_i2s (&n->id));
3945  free_neighbour (n);
3946  return GNUNET_OK;
3947 }
3948 
3949 
3953 void
3955 {
3956  if (NULL == neighbours)
3957  return;
3958  if (NULL != util_transmission_tk)
3959  {
3961  util_transmission_tk = NULL;
3962  }
3965  NULL);
3967  neighbours = NULL;
3968 }
3969 
3970 
3971 /* 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:69
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.
#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.
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
#define GNUNET_PACKED
gcc-ism to get packed structs.
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:402
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:526
struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_init(uint32_t bytes_per_second)
Create a new bandwidth value.
Definition: bandwidth.c:39
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:72
void GNUNET_BANDWIDTH_tracker_init(struct GNUNET_BANDWIDTH_Tracker *av, GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb, void *update_cb_cls, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit, uint32_t max_carry_s)
Initialize bandwidth tracker.
Definition: bandwidth.c:302
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:56
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:458
#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?
int 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:682
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:599
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ 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).
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
void * GNUNET_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.
@ 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:109
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:130
@ GNUNET_HELLO_ADDRESS_INFO_INBOUND
This is an inbound address and cannot be used to initiate an outbound connection to another peer.
#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:1296
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:1246
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
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:1269
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:200
#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:263
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:232
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:604
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:542
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:181
#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:376
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:557
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:248
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:464
#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:67
#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:329
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:35
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:135
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