GNUnet  0.10.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 (GNUNET_TIME_UNIT_MILLISECONDS, 500)
54 
59 #define QUOTA_VIOLATION_DROP_THRESHOLD 10
60 
64 #define ATS_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
65 
70 #define SETUP_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
71 
78 #define FAST_RECONNECT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
79 
83 #define UTIL_TRANSMISSION_INTERVAL GNUNET_TIME_UNIT_SECONDS
84 
89 {
94 
100 
106 };
107 
108 
110 
120 {
126 
131 
137 
138 };
139 
140 
150 {
156 
160  uint32_t nonce GNUNET_PACKED;
161 };
162 
163 
170 {
175 
180 };
181 
182 
190 {
195 
200 
206 
211  struct GNUNET_TIME_AbsoluteNBO timestamp;
212 
216  struct GNUNET_CRYPTO_EddsaPublicKey public_key;
217 
224 
225 };
226 
228 
229 
235 {
236 
241 
246 
251 
255  void *cont_cls;
256 
261  const char *message_buf;
262 
267 
272 
273 };
274 
275 
280 {
281 
286 
291 
297  struct GNUNET_TIME_Absolute connect_timestamp;
298 
302  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
303 
307  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
308 
313 
318 };
319 
320 
325 {
326 
332 
338 
343 
347  struct NeighbourAddress primary_address;
348 
353  struct NeighbourAddress alternative_address;
354 
359 
365 
370 
374  struct GNUNET_TIME_Absolute keep_alive_time;
375 
380  struct GNUNET_TIME_Absolute last_keep_alive_time;
381 
387  struct GNUNET_TIME_Absolute connect_ack_timestamp;
388 
393 
399  struct GNUNET_TIME_Absolute timeout;
400 
404  struct GNUNET_BANDWIDTH_Tracker in_tracker;
405 
411  unsigned int quota_violation_count;
412 
418  struct GNUNET_BANDWIDTH_Value32NBO neighbour_receive_quota;
419 
424 
429 
443  enum GST_ACK_State ack_state;
444 
449 
454 
458  struct GNUNET_TIME_Absolute last_util_transmission;
459 };
460 
461 
466 
471 
476 
480 static unsigned int neighbours_connected;
481 
485 static unsigned long long bytes_in_send_queue;
486 
491 
492 
499 static char *
501 {
502  switch (s) {
503  case ACK_UNDEFINED:
504  return "UNDEFINED";
505  case ACK_SEND_SYN_ACK:
506  return "SEND_SYN_ACK";
507  case ACK_SEND_ACK:
508  return "SEND_ACK";
509  default:
510  GNUNET_break (0);
511  return "N/A";
512  }
513 }
514 
515 
523 static void
525 {
526  struct QuotaSetMessage q_msg;
527  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_min;
528 
530  return;
531 #if IGNORE_INBOUND_QUOTA
532  bandwidth_min = n->primary_address.bandwidth_out;
533 #else
536 #endif
537 
539  "Sending outbound quota of %u Bps for peer `%s' to all clients\n",
540  ntohl (bandwidth_min.value__),
541  GNUNET_i2s (&n->id));
542  q_msg.header.size = htons (sizeof (struct QuotaSetMessage));
544  q_msg.quota = bandwidth_min;
545  q_msg.peer = n->id;
547  GNUNET_NO);
548 }
549 
550 
556 static void
558 {
559  size_t len = sizeof(struct ConnectInfoMessage);
560  char buf[len] GNUNET_ALIGN;
561  struct ConnectInfoMessage *connect_msg = (struct ConnectInfoMessage *) buf;
562  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_min;
563 
564 #if IGNORE_INBOUND_QUOTA
565  bandwidth_min = n->primary_address.bandwidth_out;
566 #else
569 #endif
571  "We are now connected to peer `%s'\n",
572  GNUNET_i2s (&n->id));
573  connect_msg->header.size = htons (sizeof(buf));
574  connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
575  connect_msg->id = n->id;
576  connect_msg->quota_out = bandwidth_min;
577  GST_clients_broadcast (&connect_msg->header,
578  GNUNET_NO);
579 }
580 
581 
588 static void
590 {
592  "Peer `%s' disconnected\n",
593  GNUNET_i2s (&n->id));
596 }
597 
598 
610 static void
612  const struct GNUNET_HELLO_Address *address,
614  struct GNUNET_TIME_Absolute state_timeout,
615  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
616  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
617 {
618  (void) bandwidth_in;
619  (void) bandwidth_out;
621  "Notifying about change for peer `%s' with address `%s' in state `%s' timing out at %s\n",
622  GNUNET_i2s (peer),
623  GST_plugins_a2s (address),
624  GNUNET_TRANSPORT_ps2s (state),
626  /* FIXME: include bandwidth in notification! */
628  address,
629  state,
630  state_timeout);
631 }
632 
633 
640 static struct NeighbourMapEntry *
642 {
643  if (NULL == neighbours)
644  return NULL;
645  return GNUNET_CONTAINER_multipeermap_get (neighbours, pid);
646 }
647 
648 
655 static int
657 {
658  if (NULL == n)
659  return GNUNET_NO;
661 }
662 
663 
671 static void
673 {
674  if (GNUNET_YES == na->ats_active)
676  GNUNET_NO);
677  if (NULL != na->address)
678  {
680  na->session);
682  na->address = NULL;
683  }
686  na->ats_active = GNUNET_NO;
687  na->keep_alive_nonce = 0;
688  na->session = NULL;
689 }
690 
691 
699 static void
700 master_task (void *cls);
701 
702 
710 static void
713  struct GNUNET_TIME_Absolute timeout)
714 {
717  {
720  gettext_noop ("# peers connected"),
722  GNUNET_NO);
723  }
724  if ((! GNUNET_TRANSPORT_is_connected (s)) &&
726  {
728  gettext_noop ("# peers connected"),
730  GNUNET_NO);
732  }
733  n->state = s;
734  if ( (timeout.abs_value_us < n->timeout.abs_value_us) &&
735  (NULL != n->task ) )
736  {
737  /* new timeout is earlier, reschedule master task */
739  n->task = GNUNET_SCHEDULER_add_at (timeout,
740  &master_task,
741  n);
742  }
743  n->timeout = timeout;
745  "Neighbour `%s' changed state to %s with timeout %s\n",
746  GNUNET_i2s (&n->id),
751  n->state,
752  n->timeout,
755 }
756 
757 
769 static void
771  const struct GNUNET_HELLO_Address *address,
772  struct GNUNET_ATS_Session *session,
773  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
774  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
775 {
777 
778  if (NULL == (papi = GST_plugins_find (address->transport_name)))
779  {
780  GNUNET_break (0);
781  return;
782  }
783  if (session == n->alternative_address.session)
784  {
785  n->alternative_address.bandwidth_in = bandwidth_in;
786  n->alternative_address.bandwidth_out = bandwidth_out;
787  return;
788  }
789  if (NULL != n->alternative_address.address)
790  {
792  "Replacing existing alternative address with another one\n");
794  }
795  if (NULL == session)
796  session = papi->get_session (papi->cls,
797  address);
798  if (NULL == session)
799  {
801  "Failed to obtain new session for peer `%s' and address '%s'\n",
802  GNUNET_i2s (&address->peer),
803  GST_plugins_a2s (address));
805  gettext_noop ("# session creation failed"),
806  1,
807  GNUNET_NO);
808  return;
809  }
810  GST_ats_new_session (address,
811  session);
813  "Neighbour `%s' configured alternative address %s\n",
814  GNUNET_i2s (&n->id),
815  GST_plugins_a2s(address));
816 
818  n->alternative_address.bandwidth_in = bandwidth_in;
819  n->alternative_address.bandwidth_out = bandwidth_out;
820  n->alternative_address.session = session;
826 }
827 
828 
845 static struct GNUNET_TIME_Relative
847  const void *msgbuf,
848  size_t msgbuf_size,
849  uint32_t priority,
850  struct GNUNET_TIME_Relative timeout,
851  unsigned int use_keepalive_timeout,
853  void *cont_cls)
854 {
857 
858  GNUNET_assert (NULL != n->primary_address.session);
859  if ( ((NULL == (papi = GST_plugins_find (n->primary_address.address->transport_name)) ||
860  (-1 == papi->send (papi->cls,
861  n->primary_address.session,
862  msgbuf,
863  msgbuf_size,
864  priority,
865  (result = (GNUNET_NO == use_keepalive_timeout) ? timeout :
867  papi->query_keepalive_factor (papi->cls))),
868  cont,
869  cont_cls)))) &&
870  (NULL != cont))
871  cont (cont_cls,
872  &n->id,
874  msgbuf_size,
875  0);
876  GST_neighbours_notify_data_sent (n->primary_address.address,
877  n->primary_address.session,
878  msgbuf_size);
879  GNUNET_break (NULL != papi);
880  return result;
881 }
882 
883 
890 static void
892 {
893  /* Notify monitoring about change */
894  if (NULL == n->primary_address.address)
895  return;
897  "Disabling primary address\n");
900  n->state,
901  n->timeout,
905 }
906 
907 
913 static void
915 {
916  struct MessageQueue *mq;
917 
919  "Freeing neighbour state of peer `%s'\n",
920  GNUNET_i2s (&n->id));
921  n->is_active = NULL; /* always free'd by its own continuation! */
922 
923  /* fail messages currently in the queue */
924  while (NULL != (mq = n->messages_head))
925  {
927  n->messages_tail,
928  mq);
929  if (NULL != mq->cont)
930  mq->cont (mq->cont_cls,
932  mq->message_buf_size,
933  0);
934  GNUNET_free (mq);
935  }
936  /* Mark peer as disconnected */
940  /* free addresses and mark as unused */
942 
943  if (NULL != n->alternative_address.address)
944  {
946  "Cleaning up alternative address\n");
948  }
951  &n->id,
952  n));
953 
954  /* Cancel address requests for this peer */
955  if (NULL != n->suggest_handle)
956  {
958  n->suggest_handle = NULL;
959  }
960 
961  /* Cancel the disconnect task */
962  if (NULL != n->delayed_disconnect_task)
963  {
965  n->delayed_disconnect_task = NULL;
966  }
967 
968  /* Cancel the master task */
969  if (NULL != n->task)
970  {
972  n->task = NULL;
973  }
974  /* free rest of memory */
975  GNUNET_free (n);
976 }
977 
978 
989 static void
991  const struct GNUNET_PeerIdentity *target,
992  int result,
993  size_t payload,
994  size_t physical)
995 {
996  struct NeighbourMapEntry *n;
997 
998  (void) cls;
999  (void) result;
1000  (void) payload;
1001  (void) physical;
1002  n = lookup_neighbour (target);
1003  if (NULL == n)
1004  return; /* already gone */
1006  return; /* have created a fresh entry since */
1007  if (NULL != n->task)
1010 }
1011 
1012 
1018 static void
1020 {
1021  struct GNUNET_ATS_SessionDisconnectMessage disconnect_msg;
1022 
1024  "Sending DISCONNECT message to peer `%4s'\n",
1025  GNUNET_i2s (&n->id));
1026  disconnect_msg.header.size = htons (sizeof (struct GNUNET_ATS_SessionDisconnectMessage));
1027  disconnect_msg.header.type =
1029  disconnect_msg.reserved = htonl (0);
1030  disconnect_msg.purpose.size =
1031  htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
1032  sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) +
1033  sizeof (struct GNUNET_TIME_AbsoluteNBO));
1034  disconnect_msg.purpose.purpose =
1036  disconnect_msg.timestamp =
1038  disconnect_msg.public_key = GST_my_identity.public_key;
1041  &disconnect_msg.purpose,
1042  &disconnect_msg.signature));
1043 
1044  (void) send_with_session (n,
1045  &disconnect_msg,
1046  sizeof (disconnect_msg),
1047  UINT32_MAX,
1049  GNUNET_NO,
1051  NULL);
1053  gettext_noop ("# DISCONNECT messages sent"),
1054  1,
1055  GNUNET_NO);
1056 }
1057 
1058 
1064 static void
1066 {
1068  "Disconnecting from peer %s in state %s\n",
1069  GNUNET_i2s (&n->id),
1071  /* depending on state, notify neighbour and/or upper layers of this peer
1072  about disconnect */
1073  switch (n->state)
1074  {
1077  /* other peer is completely unaware of us, no need to send DISCONNECT */
1078  free_neighbour (n);
1079  return;
1081  send_disconnect (n);
1085  break;
1087  /* we never ACK'ed the other peer's request, no need to send DISCONNECT */
1088  free_neighbour (n);
1089  return;
1091  /* we DID ACK the other peer's request, must send DISCONNECT */
1092  send_disconnect (n);
1096  break;
1100  /* we are currently connected, need to send disconnect and do
1101  internal notifications and update statistics */
1102  send_disconnect (n);
1106  break;
1108  /* Disconnecting while waiting for an ATS address to reconnect,
1109  * cannot send DISCONNECT */
1110  free_neighbour (n);
1111  return;
1113  /* already disconnected, ignore */
1114  break;
1116  /* already cleaned up, how did we get here!? */
1117  GNUNET_assert (0);
1118  break;
1119  default:
1121  "Unhandled state `%s'\n",
1123  GNUNET_break (0);
1124  break;
1125  }
1126  /* schedule timeout to clean up */
1127  if (NULL != n->task)
1130  &master_task,
1131  n);
1132 }
1133 
1134 
1145 static int
1148 {
1150  "Setting inbound quota of %u Bps for peer `%s' to all clients\n",
1151  ntohl (quota.value__), GNUNET_i2s (&n->id));
1153  quota);
1154  if (0 != ntohl (quota.value__))
1155  {
1156  struct GNUNET_ATS_SessionQuotaMessage sqm;
1157 
1158  sqm.header.size = htons (sizeof (struct GNUNET_ATS_SessionQuotaMessage));
1160  sqm.quota = quota.value__;
1161  if (NULL != n->primary_address.session)
1162  (void) send_with_session (n,
1163  &sqm,
1164  sizeof (sqm),
1165  UINT32_MAX - 1,
1167  GNUNET_NO,
1168  NULL, NULL);
1169  return GNUNET_YES;
1170  }
1172  "Disconnecting peer `%s' due to SET_QUOTA\n",
1173  GNUNET_i2s (&n->id));
1174  if (GNUNET_YES == test_connected (n))
1176  gettext_noop ("# disconnects due to quota of 0"),
1177  1, GNUNET_NO);
1179  return GNUNET_NO;
1180 }
1181 
1182 
1194 static void
1196  const struct GNUNET_HELLO_Address *address,
1197  struct GNUNET_ATS_Session *session,
1198  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
1199  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
1200 {
1201  if (session == n->primary_address.session)
1202  {
1204  GNUNET_YES);
1205  if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__)
1206  {
1207  n->primary_address.bandwidth_in = bandwidth_in;
1208  if (GNUNET_YES !=
1209  set_incoming_quota (n,
1210  bandwidth_in))
1211  return;
1212  }
1213  if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__)
1214  {
1215  n->primary_address.bandwidth_out = bandwidth_out;
1217  }
1218  return;
1219  }
1220  if ( (NULL != n->primary_address.address) &&
1221  (0 == GNUNET_HELLO_address_cmp (address,
1222  n->primary_address.address)) )
1223  {
1224  GNUNET_break (0);
1225  return;
1226  }
1227  if (NULL == session)
1228  {
1229  GNUNET_break (0);
1230  GST_ats_block_address (address,
1231  session);
1232  return;
1233  }
1234  if (NULL != n->primary_address.address)
1235  {
1237  "Replacing existing primary address with another one\n");
1239  }
1241  n->primary_address.bandwidth_in = bandwidth_in;
1242  n->primary_address.bandwidth_out = bandwidth_out;
1243  n->primary_address.session = session;
1247  n->primary_address.session));
1248  /* subsystems about address use */
1250  GNUNET_YES);
1251  if (GNUNET_YES !=
1252  set_incoming_quota (n,
1253  bandwidth_in))
1254  return;
1257  "Neighbour `%s' switched to address `%s'\n",
1258  GNUNET_i2s (&n->id),
1259  GST_plugins_a2s(address));
1260 
1263  n->state,
1264  n->timeout,
1267 }
1268 
1269 
1279 static void
1281  const struct GNUNET_PeerIdentity *receiver,
1282  int success,
1283  size_t size_payload,
1284  size_t physical)
1285 {
1286  struct MessageQueue *mq = cls;
1287  struct NeighbourMapEntry *n;
1288 
1289  if (NULL == (n = lookup_neighbour (receiver)))
1290  {
1291  if (NULL != mq->cont)
1292  mq->cont (mq->cont_cls,
1293  GNUNET_SYSERR /* not connected */,
1294  size_payload,
1295  0);
1296  GNUNET_free (mq);
1297  return; /* disconnect or other error while transmitting, can happen */
1298  }
1299  if (n->is_active == mq)
1300  {
1301  /* this is still "our" neighbour, remove us from its queue
1302  and allow it to send the next message now */
1303  n->is_active = NULL;
1304  if (NULL != n->task)
1307  n);
1308  }
1309  if (bytes_in_send_queue < mq->message_buf_size)
1310  {
1312  "Bytes_in_send_queue `%llu', Message_size %u, result: %s, payload %u, on wire %u\n",
1314  (unsigned int) mq->message_buf_size,
1315  (GNUNET_OK == success) ? "OK" : "FAIL",
1316  (unsigned int) size_payload,
1317  (unsigned int) physical);
1318  GNUNET_break (0);
1319  }
1320 
1321  GNUNET_break (size_payload == mq->message_buf_size);
1324  gettext_noop ("# bytes in message queue for other peers"),
1326  GNUNET_NO);
1327  if (GNUNET_OK == success)
1329  gettext_noop ("# messages transmitted to other peers"),
1330  1,
1331  GNUNET_NO);
1332  else
1334  gettext_noop
1335  ("# transmission failures for messages to other peers"),
1336  1, GNUNET_NO);
1338  "Sending message to `%s' of type %u with %u bytes was a %s\n",
1339  GNUNET_i2s (receiver),
1340  ntohs (((struct GNUNET_MessageHeader *) mq->message_buf)->type),
1341  (unsigned int) mq->message_buf_size,
1342  (success == GNUNET_OK) ? "success" : "FAILURE");
1343  if (NULL != mq->cont)
1344  mq->cont (mq->cont_cls,
1345  success,
1346  size_payload,
1347  physical);
1348  GNUNET_free (mq);
1349 }
1350 
1351 
1363 static void
1365 {
1366  struct MessageQueue *mq;
1367  struct GNUNET_TIME_Relative timeout;
1368 
1369  if (NULL == n->primary_address.address)
1370  {
1371  /* no address, why are we here? */
1372  GNUNET_break (0);
1373  return;
1374  }
1375  if ((0 == n->primary_address.address->address_length) &&
1376  (NULL == n->primary_address.session))
1377  {
1378  /* no address, why are we here? */
1379  GNUNET_break (0);
1380  return;
1381  }
1382  if (NULL != n->is_active)
1383  {
1384  /* transmission already pending */
1385  return;
1386  }
1387 
1388  /* timeout messages from the queue that are past their due date */
1389  while (NULL != (mq = n->messages_head))
1390  {
1392  if (timeout.rel_value_us > 0)
1393  break;
1395  gettext_noop ("# messages timed out while in transport queue"),
1396  1,
1397  GNUNET_NO);
1399  n->messages_tail,
1400  mq);
1401  n->is_active = mq;
1403  &n->id,
1404  GNUNET_SYSERR,
1405  mq->message_buf_size,
1406  0); /* timeout */
1407  }
1408  if (NULL == mq)
1409  return; /* no more messages */
1410  if (NULL == n->primary_address.address)
1411  {
1412  /* transmit_send_continuation() caused us to drop session,
1413  can't try transmission anymore. */
1414  return;
1415  }
1416 
1417 
1419  n->messages_tail,
1420  mq);
1421  n->is_active = mq;
1422 
1424  "Giving message with %u bytes to plugin session %p\n",
1425  (unsigned int) mq->message_buf_size,
1427  (void) send_with_session (n,
1428  mq->message_buf,
1429  mq->message_buf_size,
1430  0 /* priority */,
1431  timeout,
1432  GNUNET_NO,
1434  mq);
1435 }
1436 
1437 
1446 static void
1448 {
1450  struct GNUNET_TIME_Relative timeout;
1451  uint32_t nonce;
1452 
1456  return; /* no keepalive needed at this time */
1457 
1458  nonce = 0; /* 0 indicates 'not set' */
1459  while (0 == nonce)
1461  UINT32_MAX);
1462 
1464  "Sending KEEPALIVE to peer `%s' with nonce %u\n",
1465  GNUNET_i2s (&n->id),
1466  nonce);
1467  m.header.size = htons (sizeof (struct GNUNET_ATS_SessionKeepAliveMessage));
1469  m.nonce = htonl (nonce);
1470 
1471  timeout = send_with_session (n,
1472  &m,
1473  sizeof (m),
1474  UINT32_MAX /* priority */,
1476  GNUNET_YES,
1477  NULL, NULL);
1479  gettext_noop ("# KEEPALIVES sent"),
1480  1,
1481  GNUNET_NO);
1482  n->primary_address.keep_alive_nonce = nonce;
1486 }
1487 
1488 
1496 void
1498  const struct GNUNET_MessageHeader *m)
1499 {
1500  struct NeighbourMapEntry *n;
1501  const struct GNUNET_ATS_SessionKeepAliveMessage *msg_in;
1503 
1504  if (sizeof (struct GNUNET_ATS_SessionKeepAliveMessage) != ntohs (m->size))
1505  {
1506  GNUNET_break_op (0);
1507  return;
1508  }
1509 
1510  msg_in = (const struct GNUNET_ATS_SessionKeepAliveMessage *) m;
1511  if (NULL == (n = lookup_neighbour (neighbour)))
1512  {
1514  gettext_noop
1515  ("# KEEPALIVE messages discarded (peer unknown)"),
1516  1, GNUNET_NO);
1517  return;
1518  }
1519  if (NULL == n->primary_address.session)
1520  {
1522  gettext_noop
1523  ("# KEEPALIVE messages discarded (no session)"),
1524  1, GNUNET_NO);
1525  return;
1526  }
1527 
1529  "Received KEEPALIVE request from peer `%s' with nonce %u\n",
1530  GNUNET_i2s (&n->id),
1531  ntohl (msg_in->nonce));
1533  gettext_noop ("# KEEPALIVES received in good order"),
1534  1,
1535  GNUNET_NO);
1536 
1537  /* send reply to allow neighbour to measure latency */
1538  msg.header.size = htons (sizeof (struct GNUNET_ATS_SessionKeepAliveMessage));
1540  msg.nonce = msg_in->nonce;
1541  (void) send_with_session (n,
1542  &msg,
1543  sizeof (struct GNUNET_ATS_SessionKeepAliveMessage),
1544  UINT32_MAX /* priority */,
1546  GNUNET_YES,
1547  NULL, NULL);
1548 }
1549 
1550 
1559 void
1561  const struct GNUNET_MessageHeader *m)
1562 {
1563  struct NeighbourMapEntry *n;
1565  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1566  struct GNUNET_TIME_Relative latency;
1567 
1568  if (sizeof (struct GNUNET_ATS_SessionKeepAliveMessage) != ntohs (m->size))
1569  {
1570  GNUNET_break_op (0);
1571  return;
1572  }
1573 
1574  msg = (const struct GNUNET_ATS_SessionKeepAliveMessage *) m;
1575  if (NULL == (n = lookup_neighbour (neighbour)))
1576  {
1578  gettext_noop ("# KEEPALIVE_RESPONSEs discarded (not connected)"),
1579  1,
1580  GNUNET_NO);
1581  return;
1582  }
1583  if ( (GNUNET_TRANSPORT_PS_CONNECTED != n->state) ||
1585  {
1587  gettext_noop ("# KEEPALIVE_RESPONSEs discarded (not expected)"),
1588  1,
1589  GNUNET_NO);
1590  return;
1591  }
1592  if (NULL == n->primary_address.address)
1593  {
1595  gettext_noop ("# KEEPALIVE_RESPONSEs discarded (address changed)"),
1596  1,
1597  GNUNET_NO);
1598  return;
1599  }
1600  if (n->primary_address.keep_alive_nonce != ntohl (msg->nonce))
1601  {
1602  if (0 == n->primary_address.keep_alive_nonce)
1604  gettext_noop ("# KEEPALIVE_RESPONSEs discarded (no nonce)"),
1605  1,
1606  GNUNET_NO);
1607  else
1609  gettext_noop ("# KEEPALIVE_RESPONSEs discarded (bad nonce)"),
1610  1,
1611  GNUNET_NO);
1612  return;
1613  }
1615  gettext_noop ("# KEEPALIVE_RESPONSEs received (OK)"),
1616  1,
1617  GNUNET_NO);
1618 
1619 
1620  /* Update session timeout here */
1621  if (NULL != (papi = GST_plugins_find (n->primary_address.address->transport_name)))
1622  {
1624  "Updating session for peer `%s' for session %p\n",
1625  GNUNET_i2s (&n->id),
1627  papi->update_session_timeout (papi->cls,
1628  &n->id,
1630  }
1631  else
1632  {
1633  GNUNET_break (0);
1634  }
1635 
1639  n->state,
1641 
1644  "Received KEEPALIVE_RESPONSE from peer `%s', latency is %s\n",
1645  GNUNET_i2s (&n->id),
1647  GNUNET_YES));
1649  GNUNET_TIME_relative_divide (latency,
1650  2));
1651 }
1652 
1653 
1666 struct GNUNET_TIME_Relative
1668  ssize_t size,
1669  int *do_forward)
1670 {
1671  struct NeighbourMapEntry *n;
1672  struct GNUNET_TIME_Relative ret;
1673 
1674  if (NULL == neighbours)
1675  {
1676  *do_forward = GNUNET_NO;
1677  return GNUNET_TIME_UNIT_FOREVER_REL; /* This can happen during shutdown */
1678  }
1679  if (NULL == (n = lookup_neighbour (sender)))
1680  {
1682  gettext_noop ("# messages discarded due to lack of neighbour record"),
1683  1,
1684  GNUNET_NO);
1685  *do_forward = GNUNET_NO;
1686  return GNUNET_TIME_UNIT_ZERO;
1687  }
1688  if (! test_connected (n))
1689  {
1690  *do_forward = GNUNET_SYSERR;
1691  return GNUNET_TIME_UNIT_ZERO;
1692  }
1694  {
1695  n->quota_violation_count++;
1697  "Bandwidth quota (%u b/s) violation detected (total of %u).\n",
1700  /* Discount 32k per violation */
1701  GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, -32 * 1024);
1702  }
1703  else
1704  {
1705  if (n->quota_violation_count > 0)
1706  {
1707  /* try to add 32k back */
1709  n->quota_violation_count--;
1710  }
1711  }
1713  {
1715  gettext_noop
1716  ("# bandwidth quota violations by other peers"),
1717  1, GNUNET_NO);
1718  *do_forward = GNUNET_NO;
1720  }
1721  *do_forward = GNUNET_YES;
1722  ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 32 * 1024);
1723  if (ret.rel_value_us > 0)
1724  {
1726  "Throttling read (%lld bytes excess at %u b/s), waiting %s before reading more.\n",
1728  (unsigned int) n->in_tracker.available_bytes_per_s__,
1731  gettext_noop ("# ms throttling suggested"),
1732  (int64_t) ret.rel_value_us / 1000LL,
1733  GNUNET_NO);
1734  }
1735  return ret;
1736 }
1737 
1738 
1749 void
1751  const void *msg,
1752  size_t msg_size,
1753  struct GNUNET_TIME_Relative timeout,
1755  void *cont_cls)
1756 {
1757  struct NeighbourMapEntry *n;
1758  struct MessageQueue *mq;
1759 
1760  /* All ove these cases should never happen; they are all API violations.
1761  But we check anyway, just to be sure. */
1762  if (NULL == (n = lookup_neighbour (target)))
1763  {
1764  GNUNET_break (0);
1765  if (NULL != cont)
1766  cont (cont_cls,
1767  GNUNET_SYSERR,
1768  msg_size,
1769  0);
1770  return;
1771  }
1772  if (GNUNET_YES != test_connected (n))
1773  {
1774  GNUNET_break (0);
1775  if (NULL != cont)
1776  cont (cont_cls,
1777  GNUNET_SYSERR,
1778  msg_size,
1779  0);
1780  return;
1781  }
1782  bytes_in_send_queue += msg_size;
1784  gettext_noop
1785  ("# bytes in message queue for other peers"),
1787  mq = GNUNET_malloc (sizeof (struct MessageQueue) + msg_size);
1788  mq->cont = cont;
1789  mq->cont_cls = cont_cls;
1790  GNUNET_memcpy (&mq[1], msg, msg_size);
1791  mq->message_buf = (const char *) &mq[1];
1792  mq->message_buf_size = msg_size;
1793  mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1794 
1796  "Enqueueing %u bytes to send to peer %s\n",
1797  (unsigned int) msg_size,
1798  GNUNET_i2s (target));
1800  n->messages_tail,
1801  mq);
1802  if (NULL != n->task)
1805 }
1806 
1807 
1820 static void
1822  const struct GNUNET_PeerIdentity *target,
1823  int result,
1824  size_t size_payload,
1825  size_t size_on_wire)
1826 {
1827  struct NeighbourMapEntry *n;
1828 
1829  (void) cls;
1830  (void) size_payload;
1831  (void) size_on_wire;
1832  n = lookup_neighbour (target);
1833  if (NULL == n)
1834  {
1835  /* SYN continuation was called after neighbor was freed,
1836  * for example due to a time out for the state or the session
1837  * used was already terminated: nothing to do here... */
1838  return;
1839  }
1840 
1841  if ( (GNUNET_TRANSPORT_PS_SYN_SENT != n->state) &&
1844  {
1845  /* SYN continuation was called after neighbor changed state,
1846  * for example due to a time out for the state or the session
1847  * used was already terminated: nothing to do here... */
1848  return;
1849  }
1850  if (GNUNET_OK == result)
1851  return;
1852 
1854  _("Failed to send SYN message to peer `%s'\n"),
1855  GNUNET_i2s (target));
1856  switch (n->state) {
1858  /* Remove address and request an additional one */
1863  break;
1865  /* Remove address and request an additional one */
1870  break;
1872  /* Remove address and request and go back to primary address */
1874  gettext_noop ("# Failed attempts to switch addresses (failed to send SYN CONT)"),
1875  1,
1876  GNUNET_NO);
1878  "Switch failed, cleaning up alternative address\n");
1883  break;
1884  default:
1886  break;
1887  }
1888 }
1889 
1890 
1896 static void
1898 {
1899  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1900  struct TransportSynMessage connect_msg;
1901  struct NeighbourMapEntry *n;
1902 
1903  GNUNET_assert (NULL != na->session);
1905  "Sending SYN message to peer `%s' at %s\n",
1906  GNUNET_i2s (&na->address->peer),
1907  GST_plugins_a2s (na->address));
1908 
1909  papi = GST_plugins_find (na->address->transport_name);
1910  GNUNET_assert (NULL != papi);
1912  gettext_noop
1913  ("# SYN messages sent"),
1914  1, GNUNET_NO);
1916  connect_msg.header.size = htons (sizeof (struct TransportSynMessage));
1918  connect_msg.reserved = htonl (0);
1920  if (-1 ==
1921  papi->send (papi->cls,
1922  na->session,
1923  (const char *) &connect_msg,
1924  sizeof (struct TransportSynMessage),
1925  UINT_MAX,
1927  &send_session_syn_cont, NULL))
1928  {
1930  _("Failed to transmit SYN message to %s\n"),
1931  GST_plugins_a2s (na->address));
1932  n = lookup_neighbour (&na->address->peer);
1933  if (NULL == n)
1934  {
1935  GNUNET_break (0);
1936  return;
1937  }
1938  switch (n->state) {
1940  /* Remove address and request and additional one */
1941  GNUNET_assert (na == &n->primary_address);
1946  /* Hard failure to send the SYN message with this address:
1947  Destroy address and session */
1948  break;
1950  /* Remove address and request an additional one */
1951  GNUNET_assert (na == &n->primary_address);
1956  break;
1958  GNUNET_assert (na == &n->alternative_address);
1960  gettext_noop ("# Failed attempts to switch addresses (failed to send SYN)"),
1961  1,
1962  GNUNET_NO);
1963  /* Remove address and request an additional one */
1965  "Switch failed, cleaning up alternative address\n");
1970  break;
1971  default:
1972  GNUNET_break (0);
1974  break;
1975  }
1976  return;
1977  }
1979  na->session,
1980  sizeof (struct TransportSynMessage));
1981 }
1982 
1983 
1996 static void
1998  const struct GNUNET_PeerIdentity *target,
1999  int result,
2000  size_t size_payload,
2001  size_t size_on_wire)
2002 {
2003  struct NeighbourMapEntry *n;
2004 
2005  (void) cls;
2006  (void) size_payload;
2007  (void) size_on_wire;
2008  n = lookup_neighbour (target);
2009  if (NULL == n)
2010  {
2011  /* SYN_ACK continuation was called after neighbor was freed,
2012  * for example due to a time out for the state or the session
2013  * used was already terminated: nothing to do here... */
2014  return;
2015  }
2016 
2018  {
2019  /* SYN_ACK continuation was called after neighbor changed state,
2020  * for example due to a time out for the state or the session
2021  * used was already terminated: nothing to do here... */
2022  return;
2023  }
2024  if (GNUNET_OK == result)
2025  return;
2026 
2028  _("Failed to send SYN_ACK message to peer `%s' using address `%s'\n"),
2029  GNUNET_i2s (target),
2031 
2032  /* Remove address and request and additional one */
2033  /* FIXME: what if the neighbour's primary address
2034  changed in the meantime? Might want to instead
2035  pass "something" around in closure to be sure. */
2041 }
2042 
2043 
2051 static void
2053  struct GNUNET_TIME_Absolute timestamp)
2054 {
2055  const struct GNUNET_HELLO_Address *address = na->address;
2056  struct GNUNET_ATS_Session *session = na->session;
2057  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2058  struct TransportSynMessage connect_msg;
2059  struct NeighbourMapEntry *n;
2060 
2062  "Sending SYN_ACK to peer `%s'\n",
2063  GNUNET_i2s (&address->peer));
2064 
2065  if (NULL == (papi = GST_plugins_find (address->transport_name)))
2066  {
2067  GNUNET_break (0);
2068  return;
2069  }
2070  if (NULL == session)
2071  session = papi->get_session (papi->cls,
2072  address);
2073  if (NULL == session)
2074  {
2075  GNUNET_break (0);
2076  return;
2077  }
2078  GST_ats_new_session (address,
2079  session);
2081  gettext_noop
2082  ("# SYN_ACK messages sent"),
2083  1, GNUNET_NO);
2084  connect_msg.header.size = htons (sizeof (struct TransportSynMessage));
2086  connect_msg.reserved = htonl (0);
2087  connect_msg.timestamp = GNUNET_TIME_absolute_hton (timestamp);
2088 
2089  if (GNUNET_SYSERR ==
2090  papi->send (papi->cls,
2091  session,
2092  (const char *) &connect_msg,
2093  sizeof (struct TransportSynMessage),
2094  UINT_MAX,
2096  &send_session_syn_ack_cont, NULL))
2097  {
2099  _("Failed to transmit SYN_ACK message to %s\n"),
2100  GST_plugins_a2s (address));
2101 
2102  n = lookup_neighbour (&address->peer);
2103  if (NULL == n)
2104  {
2105  GNUNET_break (0);
2106  return;
2107  }
2108  /* Remove address and request and additional one */
2114  return;
2115  }
2116 }
2117 
2118 
2127 static void
2129 {
2130  struct NeighbourMapEntry *n = cls;
2131  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2132  struct GNUNET_TIME_Relative delay;
2133  int do_forward;
2134 
2135  if (NULL == n->primary_address.address)
2136  return; /* not active, ignore */
2138  GNUNET_assert (NULL != papi);
2139  if (NULL == papi->update_inbound_delay)
2140  return;
2142  0,
2143  &do_forward);
2145  "New inbound delay for peer `%s' is %llu ms\n",
2146  GNUNET_i2s (&n->id),
2147  (unsigned long long) delay.rel_value_us / 1000LL);
2148  if (NULL == n->primary_address.session)
2149  return;
2150  papi->update_inbound_delay (papi->cls,
2151  &n->id,
2153  delay);
2154 }
2155 
2156 
2163 static struct NeighbourMapEntry *
2165 {
2166  struct NeighbourMapEntry *n;
2167 
2168  if (0 ==
2169  memcmp (&GST_my_identity,
2170  peer,
2171  sizeof (struct GNUNET_PeerIdentity)))
2172  {
2174  "Cowardly refusing to consider myself my neighbour!\n");
2175  return NULL;
2176  }
2178  "Creating new neighbour entry for `%s'\n",
2179  GNUNET_i2s (peer));
2180  n = GNUNET_new (struct NeighbourMapEntry);
2181  n->id = *peer;
2182  n->ack_state = ACK_UNDEFINED;
2187  n,
2196  &n->id,
2197  n,
2200  peer,
2201  0);
2202 
2203  return n;
2204 }
2205 
2206 
2211 {
2216 
2221 
2226 
2230  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
2231 
2235  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
2236 };
2237 
2238 
2247 int
2249  const struct GNUNET_PeerIdentity *peer)
2250 {
2251  const struct TransportSynMessage *scm;
2252  struct NeighbourMapEntry *n;
2253  struct GNUNET_TIME_Absolute ts;
2254 
2255  if (ntohs (message->size) != sizeof (struct TransportSynMessage))
2256  {
2257  GNUNET_break_op (0);
2258  return GNUNET_SYSERR;
2259  }
2261  gettext_noop
2262  ("# SYN messages received"),
2263  1, GNUNET_NO);
2264  if (NULL == neighbours)
2265  {
2267  _("SYN request from peer `%s' ignored due impending shutdown\n"),
2268  GNUNET_i2s (peer));
2269  return GNUNET_OK; /* we're shutting down */
2270  }
2271  scm = (const struct TransportSynMessage *) message;
2272  GNUNET_break_op (0 == ntohl (scm->reserved));
2274  if (0 ==
2275  memcmp (&GST_my_identity,
2276  peer,
2277  sizeof (struct GNUNET_PeerIdentity)))
2278  {
2279  /* loopback connection-to-self, ignore */
2280  return GNUNET_SYSERR;
2281  }
2282  n = lookup_neighbour (peer);
2283  if (NULL == n)
2284  {
2285  /* This is a new neighbour and set to not connected */
2286  n = setup_neighbour (peer);
2287  GNUNET_assert (NULL != n);
2288  }
2289 
2290  /* Remember this SYN message in neighbour */
2292  n->connect_ack_timestamp = ts;
2293 
2295  "Received SYN for peer `%s' in state %s/%s\n",
2296  GNUNET_i2s (peer),
2298  print_ack_state (n->ack_state));
2299 
2300  switch (n->state)
2301  {
2303  /* Request an address from ATS to send SYN_ACK to this peer */
2307  break;
2309  /* SYN message takes priority over us asking ATS for address:
2310  * Wait for ATS to suggest an address and send SYN_ACK */
2314  break;
2316  /* We already wait for an address to send an SYN_ACK */
2317  break;
2320  /* Send ACK immediately */
2321  n->ack_state = ACK_SEND_ACK;
2323  ts);
2324  break;
2326  /* we are already connected and can thus send the ACK immediately */
2327  GNUNET_assert (NULL != n->primary_address.address);
2328  GNUNET_assert (NULL != n->primary_address.session);
2329  n->ack_state = ACK_SEND_ACK;
2331  ts);
2332  break;
2334  /* We wait for ATS address suggestion */
2335  break;
2337  /* We received a SYN message while waiting for a SYN_ACK in fast
2338  * reconnect. Send SYN_ACK immediately */
2339  n->ack_state = ACK_SEND_ACK;
2342  break;
2344  /* We are already connected and can thus send the ACK immediately;
2345  still, it can never hurt to have an alternative address, so also
2346  tell ATS about it */
2347  GNUNET_assert (NULL != n->primary_address.address);
2348  GNUNET_assert (NULL != n->primary_address.session);
2349  n->ack_state = ACK_SEND_ACK;
2351  ts);
2352  break;
2354  /* Get rid of remains and re-try */
2355  free_neighbour (n);
2356  n = setup_neighbour (peer);
2357  GNUNET_assert (NULL != n);
2358  /* Remember the SYN time stamp for ACK message */
2360  n->connect_ack_timestamp = ts;
2361  /* Request an address for the peer */
2365  break;
2367  /* should not be possible */
2368  GNUNET_assert (0);
2369  break;
2370  default:
2372  "Unhandled state `%s'\n",
2374  GNUNET_break (0);
2375  return GNUNET_SYSERR;
2376  }
2377  return GNUNET_OK;
2378 }
2379 
2380 
2397 static int
2399  struct GNUNET_ATS_Session *session,
2400  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
2401  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
2402 {
2403  struct NeighbourMapEntry *n;
2404 
2405  n = lookup_neighbour (&address->peer);
2406  if ( (NULL == n) ||
2407  (NULL == n->primary_address.address) ||
2408  (0 != GNUNET_HELLO_address_cmp (address,
2409  n->primary_address.address)) )
2410  return GNUNET_NO;
2411  /* We are not really switching addresses, but merely adjusting
2412  session and/or bandwidth, can do fast ATS update! */
2413  if (session != n->primary_address.session)
2414  {
2415  /* switch to a different session, but keeping same address; could
2416  happen if there is a 2nd inbound connection */
2417  n->primary_address.session = session;
2420  n->primary_address.session));
2421  }
2422  if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__)
2423  {
2424  n->primary_address.bandwidth_in = bandwidth_in;
2425  if (GNUNET_YES !=
2426  set_incoming_quota (n,
2427  bandwidth_in))
2428  return GNUNET_NO;
2429  }
2430  if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__)
2431  {
2432  n->primary_address.bandwidth_out = bandwidth_out;
2434  }
2435  return GNUNET_OK;
2436 }
2437 
2438 
2452 static void
2454  const struct GNUNET_PeerIdentity *peer,
2455  const struct GNUNET_HELLO_Address *address,
2456  struct GNUNET_ATS_Session *session,
2457  int result)
2458 {
2459  struct BlacklistCheckSwitchContext *blc_ctx = cls;
2460  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2461  struct NeighbourMapEntry *n;
2462 
2463  if (GNUNET_SYSERR == result)
2464  goto cleanup;
2465 
2466  papi = GST_plugins_find (address->transport_name);
2467  if (NULL == papi) {
2468  /* This can happen during shutdown. */
2469  goto cleanup;
2470  }
2471 
2472  if (GNUNET_NO == result)
2473  {
2475  "Blacklist denied to switch to suggested address `%s' session %p for peer `%s'\n",
2476  GST_plugins_a2s (address),
2477  session,
2478  GNUNET_i2s (peer));
2480  "# ATS suggestions ignored (blacklist denied)",
2481  1,
2482  GNUNET_NO);
2483  if (NULL != session)
2484  papi->disconnect_session (papi->cls,
2485  session);
2486  if (GNUNET_YES !=
2489  GST_ats_block_address (address,
2490  NULL);
2491  goto cleanup;
2492  }
2493 
2494 
2495  if (NULL == session)
2496  {
2497  /* need to create a session, ATS only gave us an address */
2498  session = papi->get_session (papi->cls,
2499  address);
2501  "Obtained new session for peer `%s' and address '%s': %p\n",
2502  GNUNET_i2s (&address->peer),
2503  GST_plugins_a2s (address),
2504  session);
2505  if (NULL != session)
2506  GST_ats_new_session (address,
2507  session);
2508  }
2509  if (NULL == session)
2510  {
2511  /* session creation failed, bad!, fail! */
2513  "# ATS suggestions ignored (failed to create session)",
2514  1,
2515  GNUNET_NO);
2516  /* No session could be obtained, remove blacklist check and clean up */
2518  "Failed to obtain new session for peer `%s' and address '%s'\n",
2519  GNUNET_i2s (&address->peer),
2520  GST_plugins_a2s (address));
2521  GST_ats_block_address (address,
2522  session);
2523  goto cleanup;
2524  }
2525 
2526  /* We did this check already before going into blacklist, but
2527  it is theoretically possible that the situation changed in
2528  the meantime, hence we check again here */
2529  if (GNUNET_OK ==
2530  try_run_fast_ats_update (address,
2531  session,
2532  blc_ctx->bandwidth_in,
2533  blc_ctx->bandwidth_out))
2534  goto cleanup; /* was just a minor update, we're done */
2535 
2536  /* check if we also need to setup the neighbour entry */
2537  if (NULL == (n = lookup_neighbour (peer)))
2538  {
2539  n = setup_neighbour (peer);
2540  if (NULL == n)
2541  {
2542  /* not sure how this can happen... */
2543  GNUNET_break (0);
2544  goto cleanup;
2545  }
2547  }
2548 
2550  "Peer `%s' switches to address `%s'\n",
2551  GNUNET_i2s (&address->peer),
2552  GST_plugins_a2s (address));
2553 
2554  switch (n->state)
2555  {
2557  GNUNET_break (0);
2558  GST_ats_block_address (address,
2559  session);
2560  free_neighbour (n);
2561  return;
2563  /* We requested an address and ATS suggests one:
2564  * set primary address and send SYN message*/
2566  address,
2567  session,
2568  blc_ctx->bandwidth_in,
2569  blc_ctx->bandwidth_out);
2570  if (ACK_SEND_SYN_ACK == n->ack_state)
2571  {
2572  /* Send pending SYN_ACK message */
2573  n->ack_state = ACK_SEND_ACK;
2576  }
2580  send_syn (&n->primary_address);
2581  break;
2583  /* ATS suggested a new address while waiting for an SYN_ACK:
2584  * Switch and send new SYN */
2585  /* ATS suggests a different address, switch again */
2587  address,
2588  session,
2589  blc_ctx->bandwidth_in,
2590  blc_ctx->bandwidth_out);
2591  if (ACK_SEND_SYN_ACK == n->ack_state)
2592  {
2593  /* Send pending SYN_ACK message */
2594  n->ack_state = ACK_SEND_ACK;
2597  }
2601  send_syn (&n->primary_address);
2602  break;
2604  /* We requested an address and ATS suggests one:
2605  * set primary address and send SYN_ACK message*/
2607  address,
2608  session,
2609  blc_ctx->bandwidth_in,
2610  blc_ctx->bandwidth_out);
2611  /* Send an ACK message as a response to the SYN msg */
2617  if ( (ACK_SEND_SYN_ACK == n->ack_state) ||
2618  (ACK_UNDEFINED == n->ack_state) )
2619  n->ack_state = ACK_SEND_ACK;
2620  break;
2622  /* ATS asks us to switch while we were trying to connect; switch to new
2623  address and check blacklist again */
2624  if ( (ACK_SEND_SYN_ACK == n->ack_state) )
2625  {
2626  n->ack_state = ACK_SEND_ACK;
2629  }
2631  address,
2632  session,
2633  blc_ctx->bandwidth_in,
2634  blc_ctx->bandwidth_out);
2638  break;
2640  GNUNET_assert (NULL != n->primary_address.address);
2641  GNUNET_assert (NULL != n->primary_address.session);
2642  GNUNET_break (n->primary_address.session != session);
2643  /* ATS asks us to switch a life connection; see if we can get
2644  a SYN_ACK on it before we actually do this! */
2646  address,
2647  session,
2648  blc_ctx->bandwidth_in,
2649  blc_ctx->bandwidth_out);
2654  gettext_noop ("# Attempts to switch addresses"),
2655  1,
2656  GNUNET_NO);
2658  break;
2661  address,
2662  session,
2663  blc_ctx->bandwidth_in,
2664  blc_ctx->bandwidth_out);
2665  if (ACK_SEND_SYN_ACK == n->ack_state)
2666  {
2667  /* Send pending SYN_ACK message */
2668  n->ack_state = ACK_SEND_ACK;
2671  }
2675  send_syn (&n->primary_address);
2676  break;
2678  /* ATS asks us to switch while we were trying to reconnect; switch to new
2679  address and send SYN again */
2681  address,
2682  session,
2683  blc_ctx->bandwidth_in,
2684  blc_ctx->bandwidth_out);
2688  send_syn (&n->primary_address);
2689  break;
2692  address)) &&
2693  (n->primary_address.session == session) )
2694  {
2695  /* ATS switches back to still-active session */
2697  "ATS double-switched, cleaning up alternative address\n");
2701  n->timeout);
2702  break;
2703  }
2704  /* ATS asks us to switch a life connection, send */
2706  address,
2707  session,
2708  blc_ctx->bandwidth_in,
2709  blc_ctx->bandwidth_out);
2714  break;
2716  /* not going to switch addresses while disconnecting */
2718  "# ATS suggestion ignored (disconnecting)",
2719  1,
2720  GNUNET_NO);
2721  return;
2723  GNUNET_assert (0);
2724  break;
2725  default:
2727  "Unhandled state `%s'\n",
2729  GNUNET_break (0);
2730  break;
2731  }
2732  cleanup:
2733  GNUNET_CONTAINER_DLL_remove (pending_bc_head,
2734  pending_bc_tail,
2735  blc_ctx);
2736  GNUNET_free (blc_ctx);
2737 }
2738 
2739 
2757 void
2759  struct GNUNET_ATS_Session *session,
2760  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
2761  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
2762 {
2763  struct GST_BlacklistCheck *blc;
2764  struct BlacklistCheckSwitchContext *blc_ctx;
2765 
2766  GNUNET_assert (NULL != address->transport_name);
2767  if (GNUNET_OK ==
2768  try_run_fast_ats_update (address,
2769  session,
2770  bandwidth_in,
2771  bandwidth_out))
2772  return;
2773 
2774  /* Check if plugin is available */
2775  if (NULL == (GST_plugins_find (address->transport_name)))
2776  {
2777  /* we don't have the plugin for this address */
2778  GNUNET_break (0);
2779  GST_ats_block_address (address,
2780  session);
2781  return;
2782  }
2783  if ((NULL == session) &&
2786  {
2787  /* This is a inbound address and we do not have a session to use! */
2788  GNUNET_break (0);
2789  GST_ats_block_address (address,
2790  session);
2791  return;
2792  }
2793 
2795  "ATS suggests address '%s' for peer `%s' at %u/%u speed\n",
2796  GST_plugins_a2s (address),
2797  GNUNET_i2s (&address->peer),
2798  (unsigned int) ntohl (bandwidth_in.value__),
2799  (unsigned int) ntohl (bandwidth_out.value__));
2800 
2801  /* Perform blacklist check */
2802  blc_ctx = GNUNET_new (struct BlacklistCheckSwitchContext);
2803  blc_ctx->bandwidth_in = bandwidth_in;
2804  blc_ctx->bandwidth_out = bandwidth_out;
2805  GNUNET_CONTAINER_DLL_insert (pending_bc_head,
2806  pending_bc_tail,
2807  blc_ctx);
2808  if (NULL != (blc = GST_blacklist_test_allowed (&address->peer,
2809  address->transport_name,
2811  blc_ctx,
2812  address,
2813  session)))
2814  {
2815  blc_ctx->blc = blc;
2816  }
2817 }
2818 
2819 
2829 static int
2831  const struct GNUNET_PeerIdentity *key,
2832  void *value)
2833 {
2834  struct NeighbourMapEntry *n = value;
2835  uint32_t bps_in;
2836  uint32_t bps_out;
2837  struct GNUNET_TIME_Relative delta;
2838 
2839  (void) cls;
2840  if ( (GNUNET_YES != test_connected (n)) ||
2841  (NULL == n->primary_address.address) )
2842  return GNUNET_OK;
2845  bps_in = 0;
2846  if ((0 != n->util_total_bytes_recv) && (0 != delta.rel_value_us))
2847  bps_in = (1000LL * 1000LL * n->util_total_bytes_recv) / (delta.rel_value_us);
2848  bps_out = 0;
2849  if ((0 != n->util_total_bytes_sent) && (0 != delta.rel_value_us))
2850  bps_out = (1000LL * 1000LL * n->util_total_bytes_sent) / delta.rel_value_us;
2851 
2853  "`%s' total: received %u Bytes/s, sent %u Bytes/s\n",
2854  GNUNET_i2s (key),
2855  bps_in,
2856  bps_out);
2858  bps_in,
2859  bps_out);
2860  n->util_total_bytes_recv = 0;
2861  n->util_total_bytes_sent = 0;
2863  return GNUNET_OK;
2864 }
2865 
2866 
2872 static void
2874 {
2875  (void) cls;
2876  util_transmission_tk = NULL;
2879  NULL);
2880  util_transmission_tk
2883  NULL);
2884 }
2885 
2886 
2895 void
2897  const struct GNUNET_MessageHeader *message)
2898 {
2899  struct NeighbourMapEntry *n;
2900 
2901  n = lookup_neighbour (&address->peer);
2902  if (NULL == n)
2903  return;
2904  n->util_total_bytes_recv += ntohs (message->size);
2905 }
2906 
2907 
2917 void
2919  struct GNUNET_ATS_Session *session,
2920  size_t size)
2921 {
2922  struct NeighbourMapEntry *n;
2923 
2924  n = lookup_neighbour (&address->peer);
2925  if (NULL == n)
2926  return;
2927  if (n->primary_address.session != session)
2928  return;
2930 }
2931 
2932 
2940 static void
2941 master_task (void *cls)
2942 {
2943  struct NeighbourMapEntry *n = cls;
2944  struct GNUNET_TIME_Relative delay;
2945 
2946  n->task = NULL;
2949  "Master task runs for neighbour `%s' in state %s with timeout in %s\n",
2950  GNUNET_i2s (&n->id),
2953  GNUNET_YES));
2954  switch (n->state)
2955  {
2957  /* invalid state for master task, clean up */
2958  GNUNET_break (0);
2959  free_neighbour (n);
2960  return;
2962  if (0 == delay.rel_value_us)
2963  {
2965  "Connection to `%s' timed out waiting for ATS to provide address\n",
2966  GNUNET_i2s (&n->id));
2967  free_neighbour (n);
2968  return;
2969  }
2970  break;
2972  if (0 == delay.rel_value_us)
2973  {
2975  "Connection to `%s' timed out waiting for other peer to send SYN_ACK\n",
2976  GNUNET_i2s (&n->id));
2977  /* Remove address and request and additional one */
2982  return;
2983  }
2984  break;
2986  if (0 == delay.rel_value_us)
2987  {
2989  "Connection to `%s' timed out waiting ATS to provide address to use for SYN_ACK\n",
2990  GNUNET_i2s (&n->id));
2991  free_neighbour (n);
2992  return;
2993  }
2994  break;
2996  if (0 == delay.rel_value_us)
2997  {
2999  "Connection to `%s' timed out waiting for other peer to send ACK\n",
3000  GNUNET_i2s (&n->id));
3002  return;
3003  }
3004  break;
3006  if (0 == delay.rel_value_us)
3007  {
3009  "Connection to `%s' timed out, missing KEEPALIVE_RESPONSEs\n",
3010  GNUNET_i2s (&n->id));
3012  return;
3013  }
3015  send_keepalive (n);
3016  break;
3018  if (0 == delay.rel_value_us)
3019  {
3021  "Connection to `%s' timed out, waiting for ATS replacement address\n",
3022  GNUNET_i2s (&n->id));
3024  return;
3025  }
3026  break;
3028  if (0 == delay.rel_value_us)
3029  {
3031  "Connection to `%s' timed out, waiting for other peer to SYN_ACK replacement address\n",
3032  GNUNET_i2s (&n->id));
3034  return;
3035  }
3036  break;
3038  if (0 == delay.rel_value_us)
3039  {
3041  "Switch failed, cleaning up alternative address\n");
3046  }
3048  send_keepalive (n);
3049  break;
3052  "Cleaning up connection to `%s' after sending DISCONNECT\n",
3053  GNUNET_i2s (&n->id));
3054  free_neighbour (n);
3055  return;
3057  /* how did we get here!? */
3058  GNUNET_assert (0);
3059  break;
3060  default:
3062  "Unhandled state `%s'\n",
3064  GNUNET_break (0);
3065  break;
3066  }
3070  {
3071  /* if we are *now* in one of the two states, we're sending
3072  keep alive messages, so we need to consider the keepalive
3073  delay, not just the connection timeout */
3075  delay);
3076  }
3077  if (NULL == n->task)
3078  n->task = GNUNET_SCHEDULER_add_delayed (delay,
3079  &master_task,
3080  n);
3081 }
3082 
3083 
3090 static void
3092 {
3093  struct GNUNET_MessageHeader msg;
3094 
3096  "Sending ACK message to peer `%s'\n",
3097  GNUNET_i2s (&n->id));
3098 
3099  msg.size = htons (sizeof (struct GNUNET_MessageHeader));
3101  (void) send_with_session (n,
3102  &msg,
3103  sizeof (struct GNUNET_MessageHeader),
3104  UINT32_MAX,
3106  GNUNET_NO,
3107  NULL, NULL);
3108 }
3109 
3110 
3122 int
3124  const struct GNUNET_HELLO_Address *address,
3125  struct GNUNET_ATS_Session *session)
3126 {
3127  const struct TransportSynMessage *scm;
3128  struct GNUNET_TIME_Absolute ts;
3129  struct NeighbourMapEntry *n;
3130 
3131  (void) session;
3132  if (ntohs (message->size) != sizeof (struct TransportSynMessage))
3133  {
3134  GNUNET_break_op (0);
3135  return GNUNET_SYSERR;
3136  }
3138  gettext_noop
3139  ("# SYN_ACK messages received"),
3140  1, GNUNET_NO);
3141  scm = (const struct TransportSynMessage *) message;
3142  GNUNET_break_op (ntohl (scm->reserved) == 0);
3143  if (NULL == (n = lookup_neighbour (&address->peer)))
3144  {
3146  gettext_noop
3147  ("# unexpected SYN_ACK messages (no peer)"),
3148  1, GNUNET_NO);
3149  return GNUNET_SYSERR;
3150  }
3152  "Received SYN_ACK message from peer `%s' in state %s/%s\n",
3153  GNUNET_i2s (&address->peer),
3155  print_ack_state (n->ack_state));
3157  switch (n->state)
3158  {
3160  GNUNET_break (0);
3161  free_neighbour (n);
3162  return GNUNET_SYSERR;
3165  gettext_noop ("# unexpected SYN_ACK messages (not ready)"),
3166  1,
3167  GNUNET_NO);
3168  break;
3171  {
3173  "SYN_ACK ignored as the timestamp does not match our SYN request\n");
3174  return GNUNET_OK;
3175  }
3185  break;
3189  gettext_noop ("# unexpected SYN_ACK messages (not ready)"),
3190  1,
3191  GNUNET_NO);
3192  break;
3194  /* duplicate SYN_ACK, let's answer by duplicate ACK just in case */
3196  break;
3198  /* we didn't expect any SYN_ACK, as we are waiting for ATS
3199  to give us a new address... */
3201  gettext_noop ("# unexpected SYN_ACK messages (waiting on ATS)"),
3202  1,
3203  GNUNET_NO);
3204  break;
3206  /* Reconnecting with new address address worked; go back to connected! */
3211  break;
3213  /* new address worked; adopt it and go back to connected! */
3218 
3219  /* Set primary addresses */
3226  gettext_noop ("# Successful attempts to switch addresses"),
3227  1,
3228  GNUNET_NO);
3229 
3231  memset (&n->alternative_address,
3232  0,
3233  sizeof (n->alternative_address));
3235  break;
3238  gettext_noop
3239  ("# unexpected SYN_ACK messages (disconnecting)"),
3240  1, GNUNET_NO);
3241  return GNUNET_SYSERR;
3243  GNUNET_assert (0);
3244  break;
3245  default:
3247  "Unhandled state `%s'\n",
3249  GNUNET_break (0);
3250  return GNUNET_SYSERR;
3251  }
3252  return GNUNET_OK;
3253 }
3254 
3255 
3265 int
3267  struct GNUNET_ATS_Session *session)
3268 {
3269  struct NeighbourMapEntry *n;
3270 
3271  if (NULL == (n = lookup_neighbour (peer)))
3272  return GNUNET_NO; /* can't affect us */
3273  if (session != n->primary_address.session)
3274  {
3275  /* Free alternative address */
3276  if (session == n->alternative_address.session)
3277  {
3281  n->timeout);
3283  "Session died, cleaning up alternative address\n");
3285  }
3286  return GNUNET_NO; /* doesn't affect us further */
3287  }
3288 
3290  /* The session for neighbour's primary address died */
3291  switch (n->state)
3292  {
3294  GNUNET_break (0);
3295  free_neighbour (n);
3296  return GNUNET_YES;
3298  GNUNET_break (0);
3299  free_neighbour (n);
3300  return GNUNET_YES;
3302  /* The session used to send the SYN terminated:
3303  * this implies a connect error*/
3305  "Failed to send SYN in CONNECT_SENT with `%s' %p: session terminated\n",
3308 
3309  /* Destroy the address since it cannot be used */
3314  break;
3317  /* error on inbound session; free neighbour entirely */
3318  free_neighbour (n);
3319  return GNUNET_YES;
3321  /* Our primary connection died, try a fast reconnect */
3326  break;
3328  /* we don't have an address, how can it go down? */
3329  GNUNET_break (0);
3330  break;
3333  "Failed to send SYN in RECONNECT_SENT with `%s' %p: session terminated\n",
3336  /* Destroy the address since it cannot be used */
3341  break;
3343  /* primary went down while we were waiting for SYN_ACK on secondary;
3344  secondary as primary */
3345 
3347  "Connection `%s' %p to peer `%s' was terminated while switching, "
3348  "switching to alternative address `%s' %p\n",
3351  GNUNET_i2s (peer),
3354 
3355  /* Destroy the inbound address since it cannot be used */
3360  n->primary_address.session));
3361  memset (&n->alternative_address,
3362  0,
3363  sizeof (struct NeighbourAddress));
3367  break;
3370  break;
3372  /* neighbour was freed and plugins told to terminate session */
3373  return GNUNET_NO;
3374  default:
3376  "Unhandled state `%s'\n",
3378  GNUNET_break (0);
3379  break;
3380  }
3381  if (NULL != n->task)
3384  return GNUNET_YES;
3385 }
3386 
3387 
3398 int
3400  const struct GNUNET_HELLO_Address *address,
3401  struct GNUNET_ATS_Session *session)
3402 {
3403  struct NeighbourMapEntry *n;
3404 
3405  (void) session;
3406  if (ntohs (message->size) != sizeof (struct GNUNET_MessageHeader))
3407  {
3408  GNUNET_break_op (0);
3409  return GNUNET_SYSERR;
3410  }
3412  gettext_noop ("# ACK messages received"),
3413  1,
3414  GNUNET_NO);
3415  if (NULL == (n = lookup_neighbour (&address->peer)))
3416  {
3417  GNUNET_break_op (0);
3418  return GNUNET_SYSERR;
3419  }
3421  "Received ACK for peer `%s' in state %s/%s\n",
3422  GNUNET_i2s (&address->peer),
3424  print_ack_state (n->ack_state));
3425 
3426  /* Check if we are in a plausible state for having sent
3427  a SYN_ACK. If not, return, otherwise break.
3428 
3429  The remote peers sends a ACK as a response for a SYN_ACK
3430  message.
3431 
3432  We expect a ACK:
3433  - If a remote peer has sent a SYN, we responded with a SYN_ACK and
3434  now wait for the ACK to finally be connected
3435  - If we sent a SYN_ACK to this peer before */
3436 
3437  if ( ( (GNUNET_TRANSPORT_PS_SYN_RECV_ACK != n->state) &&
3438  (ACK_SEND_ACK != n->ack_state) ) ||
3439  (NULL == n->primary_address.address) )
3440  {
3442  "Received unexpected ACK message from peer `%s' in state %s/%s\n",
3443  GNUNET_i2s (&address->peer),
3445  print_ack_state (n->ack_state));
3446 
3448  gettext_noop ("# unexpected ACK messages"),
3449  1,
3450  GNUNET_NO);
3451  return GNUNET_OK;
3452  }
3454  {
3455  /* We tried to switch addresses while being connect. We explicitly wait
3456  * for a SYN_ACK before going to GNUNET_TRANSPORT_PS_CONNECTED,
3457  * so we do not want to set the address as in use! */
3458  return GNUNET_OK;
3459  }
3463 
3464  if (NULL == n->primary_address.address) {
3465  /* See issue #3693.
3466  * We are in state = PSY_SYN_RECV_ACK or ack_state = ACK_SEND_ACK, which
3467  * really means we did try (and succeed) to send a SYN and are waiting for
3468  * an ACK.
3469  * That suggests that the primary_address used to be non-NULL, but maybe it
3470  * got reset to NULL without the state being changed appropriately?
3471  */
3472  GNUNET_break (0);
3473  return GNUNET_OK;
3474  }
3475 
3476  /* Reset backoff for primary address */
3479  return GNUNET_OK;
3480 }
3481 
3482 
3489 int
3491 {
3492  return test_connected (lookup_neighbour (target));
3493 }
3494 
3495 
3501 static void
3503 {
3504  struct NeighbourMapEntry *n = cls;
3505 
3506  n->delayed_disconnect_task = NULL;
3508  "Disconnecting by request from peer %s\n",
3509  GNUNET_i2s (&n->id));
3510  free_neighbour (n);
3511 }
3512 
3513 
3521 void
3523  const struct GNUNET_MessageHeader *msg)
3524 {
3525  struct NeighbourMapEntry *n;
3526  const struct GNUNET_ATS_SessionQuotaMessage *sqm;
3527  struct GNUNET_BANDWIDTH_Value32NBO last;
3528 
3530  "Received QUOTA message from peer `%s'\n",
3531  GNUNET_i2s (peer));
3532  if (ntohs (msg->size) != sizeof (struct GNUNET_ATS_SessionQuotaMessage))
3533  {
3534  GNUNET_break_op (0);
3536  gettext_noop ("# quota messages ignored (malformed)"),
3537  1,
3538  GNUNET_NO);
3539  return;
3540  }
3542  gettext_noop
3543  ("# QUOTA messages received"),
3544  1, GNUNET_NO);
3545  sqm = (const struct GNUNET_ATS_SessionQuotaMessage *) msg;
3546  if (NULL == (n = lookup_neighbour (peer)))
3547  {
3548  /* gone already */
3549  return;
3550  }
3552  GNUNET_BANDWIDTH_value_init (ntohl (sqm->quota)));
3553  if (last.value__ != n->neighbour_receive_quota.value__)
3554  {
3555  n->neighbour_receive_quota = last;
3557  }
3558 }
3559 
3560 
3568 void
3570  const struct GNUNET_MessageHeader *msg)
3571 {
3572  struct NeighbourMapEntry *n;
3573  const struct GNUNET_ATS_SessionDisconnectMessage *sdm;
3574 
3576  "Received DISCONNECT message from peer `%s'\n",
3577  GNUNET_i2s (peer));
3578  if (ntohs (msg->size) != sizeof (struct GNUNET_ATS_SessionDisconnectMessage))
3579  {
3580  GNUNET_break_op (0);
3582  gettext_noop
3583  ("# disconnect messages ignored (malformed)"),
3584  1,
3585  GNUNET_NO);
3586  return;
3587  }
3589  gettext_noop
3590  ("# DISCONNECT messages received"),
3591  1, GNUNET_NO);
3592  sdm = (const struct GNUNET_ATS_SessionDisconnectMessage *) msg;
3593  if (NULL == (n = lookup_neighbour (peer)))
3594  {
3595  /* gone already */
3596  return;
3597  }
3599  {
3601  gettext_noop ("# disconnect messages ignored (timestamp)"),
3602  1,
3603  GNUNET_NO);
3604  return;
3605  }
3606  if (0 != memcmp (peer,
3607  &sdm->public_key,
3608  sizeof (struct GNUNET_PeerIdentity)))
3609  {
3610  GNUNET_break_op (0);
3611  return;
3612  }
3613  if (ntohl (sdm->purpose.size) !=
3614  sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
3615  sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) +
3616  sizeof (struct GNUNET_TIME_AbsoluteNBO))
3617  {
3619  "DISCONNECT message from peer `%s' has invalid size\n",
3620  GNUNET_i2s (peer));
3621  GNUNET_break_op (0);
3622  return;
3623  }
3624  if (GNUNET_OK !=
3626  &sdm->purpose,
3627  &sdm->signature,
3628  &sdm->public_key))
3629  {
3631  "DISCONNECT message from peer `%s' cannot be verified \n",
3632  GNUNET_i2s (peer));
3633  GNUNET_break_op (0);
3634  return;
3635  }
3636  if (NULL == n->delayed_disconnect_task)
3637  {
3639  n);
3640  }
3641 }
3642 
3643 
3648 {
3653 
3657  void *cb_cls;
3658 };
3659 
3660 
3669 static int
3671  const struct GNUNET_PeerIdentity *key,
3672  void *value)
3673 {
3674  struct IteratorContext *ic = cls;
3675  struct NeighbourMapEntry *n = value;
3676  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
3677  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
3678 
3679  (void) key;
3680  if (NULL != n->primary_address.address)
3681  {
3682  bandwidth_in = n->primary_address.bandwidth_in;
3683  bandwidth_out = n->primary_address.bandwidth_out;
3684  }
3685  else
3686  {
3687  bandwidth_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
3688  bandwidth_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
3689  }
3690  ic->cb (ic->cb_cls,
3691  &n->id,
3693  n->state,
3694  n->timeout,
3695  bandwidth_in, bandwidth_out);
3696  return GNUNET_OK;
3697 }
3698 
3699 
3706 void
3708  void *cb_cls)
3709 {
3710  struct IteratorContext ic;
3711 
3712  if (NULL == neighbours)
3713  return; /* can happen during shutdown */
3714  ic.cb = cb;
3715  ic.cb_cls = cb_cls;
3718  &ic);
3719 }
3720 
3721 
3727 void
3729 {
3730  struct NeighbourMapEntry *n;
3731 
3732  if (NULL == (n = lookup_neighbour (target)))
3733  return; /* not active */
3734  if (GNUNET_YES == test_connected (n))
3736  gettext_noop ("# disconnected from peer upon explicit request"),
3737  1,
3738  GNUNET_NO);
3740  "Forced disconnect from peer %s\n",
3741  GNUNET_i2s (target));
3743 }
3744 
3745 
3752 const struct GNUNET_HELLO_Address *
3754 {
3755  struct NeighbourMapEntry *n;
3756 
3757  n = lookup_neighbour (peer);
3758  if (NULL == n)
3759  return NULL;
3760  return n->primary_address.address;
3761 }
3762 
3763 
3769 void
3770 GST_neighbours_start (unsigned int max_fds)
3771 {
3772  (void) max_fds;
3774  GNUNET_NO);
3777  NULL);
3778 }
3779 
3780 
3789 static int
3791  const struct GNUNET_PeerIdentity *key,
3792  void *value)
3793 {
3794  struct NeighbourMapEntry *n = value;
3795 
3796  (void) cls;
3797  (void) key;
3799  "Disconnecting peer `%4s' during shutdown\n",
3800  GNUNET_i2s (&n->id));
3801  free_neighbour (n);
3802  return GNUNET_OK;
3803 }
3804 
3805 
3809 void
3811 {
3812  if (NULL == neighbours)
3813  return;
3814  if (NULL != util_transmission_tk)
3815  {
3816  GNUNET_SCHEDULER_cancel (util_transmission_tk);
3817  util_transmission_tk = NULL;
3818  }
3821  NULL);
3823  neighbours = NULL;
3824 }
3825 
3826 
3827 /* 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:145
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:670
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:124
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:245
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:139
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:989
#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.
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:81
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#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).
static int ret
Final status code.
Definition: gnunet-arm.c:89
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:186
#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:208
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:99
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:196
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:1246
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
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
void * cls
Closure for all of the callbacks.
int64_t consumption_since_last_update__
Number of bytes consumed since we last updated the tracker.
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.
#define GNUNET_memcpy(dst, src, n)
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:1116
#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...
Information about ongoing sessions of the transport client.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
This is an inbound address and cannot be used to initiate an outbound connection to another peer...
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:1273
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:727
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:118
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:180
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:271
#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:79
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.
GNUNET_TRANSPORT_QueryKeepaliveFactorFunction query_keepalive_factor
Function that is used to query keepalive factor.
The identity of the host (wraps the signing key of the peer).
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:373
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:191
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:525
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
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:353
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:792
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:1223
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:654
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:965
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...