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 
109 };
110 
111 
113 
123 {
129 
134 
140 };
141 
142 
152 {
158 
162  uint32_t nonce GNUNET_PACKED;
163 };
164 
165 
172 {
177 
182 };
183 
184 
192 {
197 
202 
208 
213  struct GNUNET_TIME_AbsoluteNBO timestamp;
214 
218  struct GNUNET_CRYPTO_EddsaPublicKey public_key;
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 
295  struct GNUNET_TIME_Absolute connect_timestamp;
296 
300  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
301 
305  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
306 
311 
316 };
317 
318 
323 {
329 
335 
340 
344  struct NeighbourAddress primary_address;
345 
350  struct NeighbourAddress alternative_address;
351 
356 
362 
367 
371  struct GNUNET_TIME_Absolute keep_alive_time;
372 
377  struct GNUNET_TIME_Absolute last_keep_alive_time;
378 
384  struct GNUNET_TIME_Absolute connect_ack_timestamp;
385 
390 
396  struct GNUNET_TIME_Absolute timeout;
397 
401  struct GNUNET_BANDWIDTH_Tracker in_tracker;
402 
408  unsigned int quota_violation_count;
409 
415  struct GNUNET_BANDWIDTH_Value32NBO neighbour_receive_quota;
416 
421 
426 
440  enum GST_ACK_State ack_state;
441 
446 
451 
455  struct GNUNET_TIME_Absolute last_util_transmission;
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),
626  GST_plugins_a2s (address),
627  GNUNET_TRANSPORT_ps2s (state),
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;
648  return GNUNET_CONTAINER_multipeermap_get (neighbours, pid);
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
716  struct GNUNET_TIME_Absolute timeout)
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 */
742  n->task = GNUNET_SCHEDULER_add_at (timeout,
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),
806  GST_plugins_a2s (address));
808  gettext_noop ("# session creation failed"),
809  1,
810  GNUNET_NO);
811  return;
812  }
813  GST_ats_new_session (address,
814  session);
816  "Neighbour `%s' configured alternative address %s\n",
817  GNUNET_i2s (&n->id),
818  GST_plugins_a2s (address));
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,
853  struct GNUNET_TIME_Relative timeout,
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) &&
1237  (0 == GNUNET_HELLO_address_cmp (address,
1238  n->primary_address.address)))
1239  {
1240  GNUNET_break (0);
1241  return;
1242  }
1243  if (NULL == session)
1244  {
1245  GNUNET_break (0);
1246  GST_ats_block_address (address,
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),
1275  GST_plugins_a2s (address));
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);
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;
1386  struct GNUNET_TIME_Relative timeout;
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 {
1470  struct GNUNET_TIME_Relative timeout;
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));
1489  m.nonce = htonl (nonce);
1490 
1491  timeout = send_with_session (n,
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;
1754  ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 32 * 1024);
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,
1785  struct GNUNET_TIME_Relative timeout,
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;
1825  mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
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  }
2128  GST_ats_new_session (address,
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"),
2151  GST_plugins_a2s (address));
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 
2282  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
2283 
2287  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
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) ||
2474  (0 != GNUNET_HELLO_address_cmp (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",
2543  GST_plugins_a2s (address),
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 !=
2556  GST_ats_block_address (address,
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),
2570  GST_plugins_a2s (address),
2571  session);
2572  if (NULL != session)
2573  GST_ats_new_session (address,
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),
2587  GST_plugins_a2s (address));
2588  GST_ats_block_address (address,
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 ==
2597  try_run_fast_ats_update (address,
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),
2619  GST_plugins_a2s (address));
2620 
2621  switch (n->state)
2622  {
2624  GNUNET_break (0);
2625  GST_ats_block_address (address,
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:
2819  GNUNET_CONTAINER_DLL_remove (pending_bc_head,
2820  pending_bc_tail,
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 ==
2856  try_run_fast_ats_update (address,
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);
2867  GST_ats_block_address (address,
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);
2877  GST_ats_block_address (address,
2878  session);
2879  return;
2880  }
2881 
2883  "ATS suggests address '%s' for peer `%s' at %u/%u speed\n",
2884  GST_plugins_a2s (address),
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;
2893  GNUNET_CONTAINER_DLL_insert (pending_bc_head,
2894  pending_bc_tail,
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);
2969  util_transmission_tk
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)
3181  n->task = GNUNET_SCHEDULER_add_delayed (delay,
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);
3918  util_transmission_tk = GNUNET_SCHEDULER_add_delayed (
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  {
3960  GNUNET_SCHEDULER_cancel (util_transmission_tk);
3961  util_transmission_tk = NULL;
3962  }
3965  NULL);
3967  neighbours = NULL;
3968 }
3969 
3970 
3971 /* end of file gnunet-service-transport_neighbours.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct GNUNET_PeerIdentity GST_my_identity
Our public key.
size_t address_length
Number of bytes in address.
static struct GNUNET_CONTAINER_MultiPeerMap * neighbours
Hash map from peer identities to the respective struct NeighbourMapEntry.
Connection got into trouble, rest of the system still believes it to be up, but we&#39;re getting a new a...
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Public key of the sender.
struct GNUNET_PeerIdentity id
Identity of the new neighbour.
Definition: transport.h:141
struct BlacklistCheckSwitchContext * next
DLL next pointer.
void GST_neighbours_iterate(GST_NeighbourIterator cb, void *cb_cls)
Iterate over all connected neighbours.
We have some primary connection, but ATS suggested we switch to some alternative; we now sent a SYN m...
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
void GST_clients_broadcast(const struct GNUNET_MessageHeader *msg, int may_drop)
Broadcast the given message to all of our clients.
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
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:673
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.
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
GNUNET_TRANSPORT_PeerState
Possible state of a neighbour.
uint64_t rel_value_us
The actual value.
Context we use when performing a blacklist check.
We did not receive a SYN message for this neighbour.
Sent SYN over new address (either by ATS telling us to switch addresses or from RECONNECT_ATS); if th...
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
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.
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
common internal definitions for transport service
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...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
struct NeighbourAddress alternative_address
Alternative address currently under consideration for communicating with the neighbour.
We&#39;re finished with the disconnect; and are cleaning up the state now! We put the struct into this st...
int GST_neighbours_handle_session_syn(const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *peer)
We received a &#39;SYN&#39; message from the other peer.
unsigned int quota_violation_count
How often has the other peer (recently) violated the inbound traffic limit? Incremented by 10 per vio...
uint32_t util_total_bytes_recv
Tracking utilization of inbound bandwidth.
struct GNUNET_BANDWIDTH_Tracker in_tracker
Tracker for inbound bandwidth.
struct GNUNET_TIME_AbsoluteNBO timestamp
Absolute time at the sender.
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.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
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_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT.
Definition: transport.h:122
struct GST_BlacklistCheck * blc
Handle to the blacklist check we are performing.
int GST_neighbours_test_connected(const struct GNUNET_PeerIdentity *target)
Test if we&#39;re connected to the given peer.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
struct GNUNET_TIME_Absolute timeout
Time where we should cut the connection (timeout) if we don&#39;t make progress in the state machine (or ...
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA
Message exchanged between transport services to indicate that the sender should limit its transmissio...
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_BANDWIDTH_Value32NBO quota_out
Current outbound quota for this peer.
Definition: transport.h:135
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT.
struct GNUNET_TIME_Absolute timeout
At what time should we fail?
GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
int GST_neighbours_session_terminated(const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Session *session)
A session was terminated.
static void send_disconnect_cont(void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t payload, size_t physical)
Function called when the &#39;DISCONNECT&#39; message has been sent by the plugin.
int 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:986
#define DISCONNECT_SENT_TIMEOUT
Time we give plugin to transmit DISCONNECT message before the neighbour entry self-destructs.
static void neighbours_connect_notification(struct NeighbourMapEntry *n)
Notify our clients that another peer connected to us.
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
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in
Inbound bandwidth that was assigned to address.
struct GNUNET_TIME_Absolute connect_ack_timestamp
Timestamp we should include in our next SYN_ACK message.
GST_ACK_State
State describing which kind a reply this neighbour should send.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
Struct to track available bandwidth.
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.
Message a peer sends to another when connected to indicate that the other peer should limit transmiss...
#define GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT
Bandwidth (in/out) to assume initially (before either peer has communicated any particular preference...
interfacing between transport and ATS service
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.
#define GNUNET_NO
Definition: gnunet_common.h:78
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint32_t quota
Quota to use (for sending), in bytes per second.
void GNUNET_ATS_connectivity_suggest_cancel(struct GNUNET_ATS_ConnectivitySuggestHandle *sh)
We no longer care about being connected to a peer.
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...
Received a SYN, asking ATS about address suggestions.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
Entry in a DLL we use to keep track of pending blacklist checks.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
static char * print_ack_state(enum GST_ACK_State s)
Convert the given ACK state to a string.
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).
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA.
Time for absolute time used by GNUnet, in microseconds and in network byte order. ...
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.
uint64_t abs_value_us
The actual value.
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA.
Definition: transport.h:180
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE
Response to a GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE message to measure latency in a regular...
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT
Message from TRANSPORT notifying about a client that connected to us.
int GNUNET_TRANSPORT_is_connected(enum GNUNET_TRANSPORT_PeerState state)
Check if a state is defined as connected.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
uint32_t value__
The actual value (bytes per second).
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
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.
static unsigned int neighbours_connected
counter for connected neighbours
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 &#39;SESSION_SYN_ACK&#39; message from the other peer.
void GST_neighbours_start(unsigned int max_fds)
Initialize the neighbours subsystem.
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.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
Message a peer sends to another to indicate that it intends to setup a connection/session for data ex...
static void delayed_disconnect(void *cls)
Task to asynchronously run free_neighbour().
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
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
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...
GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout
Function that will be called whenever the transport service wants to notify the plugin that a session...
struct GNUNET_PeerIdentity peer
About which peer are we talking here?
Definition: transport.h:190
static void free_neighbour(struct NeighbourMapEntry *n)
Free a neighbour map entry.
struct GNUNET_TIME_AbsoluteNBO timestamp
Absolute time at the sender.
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...
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")...
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:130
Closure for the neighbours_iterate() function.
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:1253
Fresh peer or completely disconnected.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
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.
struct GNUNET_ATS_ConnectivitySuggestHandle * suggest_handle
ATS address suggest handle.
static struct GNUNET_STATISTICS_Handle * GST_stats
Statistics handle.
struct GNUNET_TIME_Absolute keep_alive_time
At what time should we sent the next keep-alive message?
enum State state
current state of profiling
void * cls
Closure for all of the callbacks.
int64_t consumption_since_last_update__
Number of bytes consumed since we last updated the tracker.
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
void GST_neighbours_stop()
Cleanup the neighbours subsystem.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN_ACK
Transport SYN_ACK message exchanged between transport services to indicate that a SYN message was acc...
const struct GNUNET_HELLO_Address * GST_neighbour_get_current_address(const struct GNUNET_PeerIdentity *peer)
Obtain current address information for the given neighbour.
struct NeighbourAddress primary_address
Primary address we currently use to communicate with the neighbour.
A possible address we could use to communicate with a neighbour.
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:1113
#define FAST_RECONNECT_TIMEOUT
How long are we willing to wait for a successful reconnect if an existing connection went down...
static char * value
Value of the record to add/remove.
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 &#39;ACK&#39; message from the other peer.
static int test_connected(struct NeighbourMapEntry *n)
Test if we&#39;re connected to the given peer.
#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...
Session handle for connections.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
This is an inbound address and cannot be used to initiate an outbound connection to another peer...
void GST_manipulation_peer_disconnect(const struct GNUNET_PeerIdentity *peer)
Notify manipulation about disconnect so it can discard queued messages.
struct GNUNET_TIME_Absolute connect_timestamp
Timestamp of the &#39;SESSION_CONNECT&#39; message we sent to the other peer for this address.
static void inbound_bw_tracker_update(void *cls)
Function called by the bandwidth tracker for a peer whenever the tracker&#39;s state changed such that we...
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:1280
neighbour manipulation API, allows manipulation of performance metrics (delay and towards ATS) ...
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in
Inbound bandwidth from ATS for this address.
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.
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:687
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...
Randomness for IVs etc.
static char buf[2048]
static void cleanup(void *cls)
Function scheduled as very last function, cleans up after us.
Handle for ATS address suggestion requests.
void * cont_cls
Closure for cont.
const char * transport_name
Name of the transport plugin enabling the communication using this address.
For each neighbour we keep a list of messages that we still want to transmit to the neighbour...
Message from the transport service to the library informing about neighbors.
Definition: transport.h:117
static int result
Global testing status.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
uint32_t util_total_bytes_sent
Tracking utilization of outbound bandwidth.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose of the signature.
static struct BlacklistCheckSwitchContext * pending_bc_tail
List of pending blacklist checks: tail.
struct GNUNET_PeerIdentity id
Identity of this neighbour.
static void neighbours_disconnect_notification(struct NeighbourMapEntry *n)
Notify our clients (and manipulation) that a peer disconnected from us.
struct GNUNET_ATS_Session * session
Active session for this address.
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...
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 MessageQueue * next
This is a doubly linked list.
Asked to initiate connection, trying to get address from ATS.
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...
const char * GST_plugins_a2s(const struct GNUNET_HELLO_Address *address)
Convert a given address to a human-readable format.
#define GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT
How long do we delay reading more from a peer after a quota violation?
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
Internal representation of the hash map.
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE or GNUNET_MESSAGE_TYPE_TRANSPORT_SESSI...
struct GNUNET_SCHEDULER_Task * task
Main task that drives this peer (timeouts, keepalives, etc.).
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
GNUNET_TRANSPORT_UpdateInboundDelay update_inbound_delay
Function that will be called whenever the transport service wants to notify the plugin that the inbou...
#define UTIL_TRANSMISSION_INTERVAL
Interval to send utilization data.
struct GNUNET_TRANSPORT_PluginFunctions * GST_plugins_find(const char *name)
Obtain the plugin API based on a plugin name.
Message used to set a particular bandwidth quota.
Definition: transport.h:175
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out
Outbound bandwidth that was assigned to address.
int ats_active
Did we tell ATS that this is our &#39;active&#39; address?
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static struct GNUNET_SCHEDULER_Task * util_transmission_tk
Task transmitting utilization data.
static struct NeighbourMapEntry * lookup_neighbour(const struct GNUNET_PeerIdentity *pid)
Lookup a neighbour entry in the neighbours hash map.
static unsigned long long bytes_in_send_queue
Number of bytes we have currently queued for transmission.
#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...
const char * message_buf
The message(s) we want to transmit, GNUNET_MessageHeader(s) stuck together in memory.
#define MAX_BANDWIDTH_CARRY_S
Number of seconds that available bandwidth carries over (can accumulate).
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
There must only be one value per key; storing a value should fail if a value under the same key alrea...
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:272
#define QUOTA_VIOLATION_DROP_THRESHOLD
How often must a peer violate bandwidth quotas before we start to simply drop its messages...
const char * GNUNET_TRANSPORT_ps2s(enum GNUNET_TRANSPORT_PeerState state)
Convert a transport state to a human readable string.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
GST_NeighbourIterator cb
Function to call on each connected neighbour.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:67
Message we send to the other peer to notify it that we intentionally are disconnecting (to reduce tim...
struct GNUNET_HELLO_Address * address
Network-level address information.
Sent SYN message to other peer, waiting for SYN_ACK.
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".
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
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&#39;ve been asked to switch addresses, and just now got the result from the blacklist check to see if ...
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 send_session_ack_message(struct NeighbourMapEntry *n)
Send a ACK message to the neighbour to confirm that we got its SYN_ACK.
struct GNUNET_PeerIdentity peer
For which peer is this an address?
struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_init(uint32_t bytes_per_second)
Create a new bandwidth value.
Definition: bandwidth.c:39
32-bit bandwidth used for network exchange by GNUnet, in bytes per second.
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.
Message a peer sends to another when connected to indicate that a session is in use and the peer is s...
static unsigned long long payload
How much data are we currently storing in the database?
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT
Transport DISCONNECT message exchanged between transport services to indicate that a connection shoul...
enum GNUNET_TRANSPORT_PeerState state
The current state of the peer.
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.
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_ATS_ConnectivityHandle * GST_ats_connect
ATS connectivity handle.
an ECC signature using EdDSA.
static unsigned long long quota
How much space are we allowed to use?
struct GNUNET_CRYPTO_EddsaSignature signature
Signature of the peer that sends us the disconnect.
uint32_t available_bytes_per_s__
Bandwidth limit to enforce in bytes per second.
void GST_neighbours_force_disconnect(const struct GNUNET_PeerIdentity *target)
If we have an active connection to the given target, it must be shutdown.
GST_NeighbourSendContinuation cont
Function to call once we&#39;re done.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don&#39;t receive messages from the peer...
static void send_keepalive(struct NeighbourMapEntry *n)
Send keepalive message to the neighbour.
The neighbour sent a SYN_ACK message and has to send a ACK as reply.
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.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN
Transport SYN message exchanged between transport services to indicate that a session should be marke...
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
static struct GNUNET_CRYPTO_EddsaPrivateKey * GST_my_private_key
Our private key.
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out
Outbound bandwidth from ATS for this address.
static void free_address(struct NeighbourAddress *na)
We don&#39;t need a given neighbour address any more.
The identity of the host (wraps the signing key of the peer).
static struct BlacklistCheckSwitchContext * pending_bc_head
List of pending blacklist checks: head.
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.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to &#39;struct&#39;s...
#define GNUNET_PACKED
gcc-ism to get packed structs.
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.
#define NEIGHBOUR_TABLE_SIZE
Size of the neighbour hash map.
struct BlacklistCheckSwitchContext * prev
DLL prev pointer.
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:375
int expect_latency_response
Did we sent an KEEP_ALIVE message and are we expecting a response?
void GST_ats_block_reset(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
Reset address blocking time.
struct MessageQueue * is_active
Are we currently trying to send a message? If so, which one?
struct GNUNET_BANDWIDTH_Value32NBO quota
Quota.
Definition: transport.h:185
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 send_disconnect(struct NeighbourMapEntry *n)
Transmit a DISCONNECT message to the other peer.
struct GNUNET_SCHEDULER_Task * delayed_disconnect_task
Task to disconnect neighbour after we received a DISCONNECT message.
An address for communicating with a peer.
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...
Disconnect in progress (we&#39;re sending the DISCONNECT message to the other peer; after that is finishe...
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.
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.
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.
static void disconnect_neighbour(struct NeighbourMapEntry *n)
Disconnect from the given neighbour, clean up the record.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:109
Automatic transport selection and outbound bandwidth determination.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
static int set_incoming_quota(struct NeighbourMapEntry *n, struct GNUNET_BANDWIDTH_Value32NBO quota)
Change the incoming quota for the given peer.
#define ATS_RESPONSE_TIMEOUT
How long are we willing to wait for a response from ATS before timing out?
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.
#define GNUNET_log(kind,...)
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 ...
Entry in list of pending tasks.
Definition: scheduler.c:134
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_BANDWIDTH_Value32NBO neighbour_receive_quota
Latest quota the other peer send us in bytes per second.
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 GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK
Transport ACK message exchanged between transport services to indicate that a SYN_ACK message was acc...
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA
Message telling transport to limit its receive rate.
static struct NeighbourMapEntry * setup_neighbour(const struct GNUNET_PeerIdentity *peer)
Create a fresh entry in the neighbour map for the given peer.
Header for all communications.
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:527
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
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:354
static void transmit_send_continuation(void *cls, const struct GNUNET_PeerIdentity *receiver, int success, size_t size_payload, size_t physical)
We&#39;re done with our transmission attempt, continue processing.
The neighbour received a SYN message and has to send a SYN_ACK as reply.
Got our SYN_ACK/ACK, connection is up.
static void master_task(void *cls)
Master task run for every neighbour.
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:742
size_t message_buf_size
Size of the message buf.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
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.
void(* GST_NeighbourSendContinuation)(void *cls, int success, size_t bytes_payload, size_t bytes_on_wire)
Function called after the transmission is done.
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:1230
static void utilization_transmission(void *cls)
Task transmitting utilization in a regular interval.
uint32_t keep_alive_nonce
The current nonce sent in the last keep alive messages.
uint32_t nonce
A nonce to identify the session the keep alive is used for.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:657
static char * address
GNS address for this phone.
static void send_outbound_quota_to_clients(struct NeighbourMapEntry *n)
Send information about a new outbound quota to our clients.
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN or GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN...
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
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.
SYN request from other peer was SYN_ACK&#39;ed, waiting for ACK.
#define GNUNET_HELLO_address_free(addr)
Free an 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 int neighbours_iterate(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Call the callback from the closure for each neighbour.
#define GNUNET_malloc(size)
Wrapper around malloc.
struct GNUNET_TIME_Absolute last_util_transmission
Date of last utilization transmission.
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.
#define GNUNET_free(ptr)
Wrapper around free.
struct MessageQueue * prev
This is a doubly linked list.
static void send_syn(struct NeighbourAddress *na)
Send a SYN message via the given address.
Time for relative time used by GNUnet, in microseconds.
static int disconnect_all_neighbours(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Disconnect from the given neighbour.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
#define gettext_noop(String)
Definition: gettext.h:69
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...