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 
93 
99 
105 };
106 
107 
109 
124 
129 
135 };
136 
137 
152 
156  uint32_t nonce GNUNET_PACKED;
157 };
158 
159 
170 
175 };
176 
177 
189 
194 
200 
205  struct GNUNET_TIME_AbsoluteNBO timestamp;
206 
210  struct GNUNET_CRYPTO_EddsaPublicKey public_key;
211 
218 };
219 
221 
222 
227 struct MessageQueue {
232 
237 
242 
246  void *cont_cls;
247 
252  const char *message_buf;
253 
258 
263 };
264 
265 
274 
279 
285  struct GNUNET_TIME_Absolute connect_timestamp;
286 
290  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
291 
295  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
296 
301 
306 };
307 
308 
318 
324 
329 
333  struct NeighbourAddress primary_address;
334 
339  struct NeighbourAddress alternative_address;
340 
345 
351 
356 
360  struct GNUNET_TIME_Absolute keep_alive_time;
361 
366  struct GNUNET_TIME_Absolute last_keep_alive_time;
367 
373  struct GNUNET_TIME_Absolute connect_ack_timestamp;
374 
379 
385  struct GNUNET_TIME_Absolute timeout;
386 
390  struct GNUNET_BANDWIDTH_Tracker in_tracker;
391 
397  unsigned int quota_violation_count;
398 
404  struct GNUNET_BANDWIDTH_Value32NBO neighbour_receive_quota;
405 
410 
415 
429  enum GST_ACK_State ack_state;
430 
435 
440 
444  struct GNUNET_TIME_Absolute last_util_transmission;
445 };
446 
447 
452 
457 
462 
466 static unsigned int neighbours_connected;
467 
471 static unsigned long long bytes_in_send_queue;
472 
477 
478 
485 static char *
487 {
488  switch (s)
489  {
490  case ACK_UNDEFINED:
491  return "UNDEFINED";
492 
493  case ACK_SEND_SYN_ACK:
494  return "SEND_SYN_ACK";
495 
496  case ACK_SEND_ACK:
497  return "SEND_ACK";
498 
499  default:
500  GNUNET_break(0);
501  return "N/A";
502  }
503 }
504 
505 
513 static void
515 {
516  struct QuotaSetMessage q_msg;
517  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_min;
518 
520  return;
521 #if IGNORE_INBOUND_QUOTA
522  bandwidth_min = n->primary_address.bandwidth_out;
523 #else
526 #endif
527 
529  "Sending outbound quota of %u Bps for peer `%s' to all clients\n",
530  ntohl(bandwidth_min.value__),
531  GNUNET_i2s(&n->id));
532  q_msg.header.size = htons(sizeof(struct QuotaSetMessage));
534  q_msg.quota = bandwidth_min;
535  q_msg.peer = n->id;
537  GNUNET_NO);
538 }
539 
540 
546 static void
548 {
549  size_t len = sizeof(struct ConnectInfoMessage);
550  char buf[len] GNUNET_ALIGN;
551  struct ConnectInfoMessage *connect_msg = (struct ConnectInfoMessage *)buf;
552  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_min;
553 
554 #if IGNORE_INBOUND_QUOTA
555  bandwidth_min = n->primary_address.bandwidth_out;
556 #else
559 #endif
561  "We are now connected to peer `%s'\n",
562  GNUNET_i2s(&n->id));
563  connect_msg->header.size = htons(sizeof(buf));
564  connect_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
565  connect_msg->id = n->id;
566  connect_msg->quota_out = bandwidth_min;
567  GST_clients_broadcast(&connect_msg->header,
568  GNUNET_NO);
569 }
570 
571 
578 static void
580 {
582  "Peer `%s' disconnected\n",
583  GNUNET_i2s(&n->id));
586 }
587 
588 
600 static void
602  const struct GNUNET_HELLO_Address *address,
604  struct GNUNET_TIME_Absolute state_timeout,
605  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
606  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
607 {
608  (void)bandwidth_in;
609  (void)bandwidth_out;
611  "Notifying about change for peer `%s' with address `%s' in state `%s' timing out at %s\n",
612  GNUNET_i2s(peer),
613  GST_plugins_a2s(address),
614  GNUNET_TRANSPORT_ps2s(state),
616  /* FIXME: include bandwidth in notification! */
618  address,
619  state,
620  state_timeout);
621 }
622 
623 
630 static struct NeighbourMapEntry *
632 {
633  if (NULL == neighbours)
634  return NULL;
635  return GNUNET_CONTAINER_multipeermap_get(neighbours, pid);
636 }
637 
638 
645 static int
647 {
648  if (NULL == n)
649  return GNUNET_NO;
651 }
652 
653 
661 static void
663 {
664  if (GNUNET_YES == na->ats_active)
666  GNUNET_NO);
667  if (NULL != na->address)
668  {
670  na->session);
672  na->address = NULL;
673  }
676  na->ats_active = GNUNET_NO;
677  na->keep_alive_nonce = 0;
678  na->session = NULL;
679 }
680 
681 
689 static void
690 master_task(void *cls);
691 
692 
700 static void
703  struct GNUNET_TIME_Absolute timeout)
704 {
707  {
710  gettext_noop("# peers connected"),
712  GNUNET_NO);
713  }
714  if ((!GNUNET_TRANSPORT_is_connected(s)) &&
716  {
718  gettext_noop("# peers connected"),
720  GNUNET_NO);
722  }
723  n->state = s;
724  if ((timeout.abs_value_us < n->timeout.abs_value_us) &&
725  (NULL != n->task))
726  {
727  /* new timeout is earlier, reschedule master task */
729  n->task = GNUNET_SCHEDULER_add_at(timeout,
730  &master_task,
731  n);
732  }
733  n->timeout = timeout;
735  "Neighbour `%s' changed state to %s with timeout %s\n",
736  GNUNET_i2s(&n->id),
741  n->state,
742  n->timeout,
745 }
746 
747 
759 static void
761  const struct GNUNET_HELLO_Address *address,
762  struct GNUNET_ATS_Session *session,
763  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
764  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
765 {
767 
768  if (NULL == (papi = GST_plugins_find(address->transport_name)))
769  {
770  GNUNET_break(0);
771  return;
772  }
773  if (session == n->alternative_address.session)
774  {
775  n->alternative_address.bandwidth_in = bandwidth_in;
776  n->alternative_address.bandwidth_out = bandwidth_out;
777  return;
778  }
779  if (NULL != n->alternative_address.address)
780  {
782  "Replacing existing alternative address with another one\n");
784  }
785  if (NULL == session)
786  session = papi->get_session(papi->cls,
787  address);
788  if (NULL == session)
789  {
791  "Failed to obtain new session for peer `%s' and address '%s'\n",
792  GNUNET_i2s(&address->peer),
793  GST_plugins_a2s(address));
795  gettext_noop("# session creation failed"),
796  1,
797  GNUNET_NO);
798  return;
799  }
800  GST_ats_new_session(address,
801  session);
803  "Neighbour `%s' configured alternative address %s\n",
804  GNUNET_i2s(&n->id),
805  GST_plugins_a2s(address));
806 
808  n->alternative_address.bandwidth_in = bandwidth_in;
809  n->alternative_address.bandwidth_out = bandwidth_out;
810  n->alternative_address.session = session;
816 }
817 
818 
835 static struct GNUNET_TIME_Relative
837  const void *msgbuf,
838  size_t msgbuf_size,
839  uint32_t priority,
840  struct GNUNET_TIME_Relative timeout,
841  unsigned int use_keepalive_timeout,
843  void *cont_cls)
844 {
847 
848  GNUNET_assert(NULL != n->primary_address.session);
849  if (((NULL == (papi = GST_plugins_find(n->primary_address.address->transport_name)) ||
850  (-1 == papi->send(papi->cls,
851  n->primary_address.session,
852  msgbuf,
853  msgbuf_size,
854  priority,
855  (result = (GNUNET_NO == use_keepalive_timeout) ? timeout :
857  papi->query_keepalive_factor(papi->cls))),
858  cont,
859  cont_cls)))) &&
860  (NULL != cont))
861  cont(cont_cls,
862  &n->id,
864  msgbuf_size,
865  0);
866  GST_neighbours_notify_data_sent(n->primary_address.address,
867  n->primary_address.session,
868  msgbuf_size);
869  GNUNET_break(NULL != papi);
870  return result;
871 }
872 
873 
880 static void
882 {
883  /* Notify monitoring about change */
884  if (NULL == n->primary_address.address)
885  return;
887  "Disabling primary address\n");
890  n->state,
891  n->timeout,
895 }
896 
897 
903 static void
905 {
906  struct MessageQueue *mq;
907 
909  "Freeing neighbour state of peer `%s'\n",
910  GNUNET_i2s(&n->id));
911  n->is_active = NULL; /* always free'd by its own continuation! */
912 
913  /* fail messages currently in the queue */
914  while (NULL != (mq = n->messages_head))
915  {
917  n->messages_tail,
918  mq);
919  if (NULL != mq->cont)
920  mq->cont(mq->cont_cls,
922  mq->message_buf_size,
923  0);
924  GNUNET_free(mq);
925  }
926  /* Mark peer as disconnected */
930  /* free addresses and mark as unused */
932 
933  if (NULL != n->alternative_address.address)
934  {
936  "Cleaning up alternative address\n");
938  }
941  &n->id,
942  n));
943 
944  /* Cancel address requests for this peer */
945  if (NULL != n->suggest_handle)
946  {
948  n->suggest_handle = NULL;
949  }
950 
951  /* Cancel the disconnect task */
952  if (NULL != n->delayed_disconnect_task)
953  {
955  n->delayed_disconnect_task = NULL;
956  }
957 
958  /* Cancel the master task */
959  if (NULL != n->task)
960  {
962  n->task = NULL;
963  }
964  /* free rest of memory */
965  GNUNET_free(n);
966 }
967 
968 
979 static void
981  const struct GNUNET_PeerIdentity *target,
982  int result,
983  size_t payload,
984  size_t physical)
985 {
986  struct NeighbourMapEntry *n;
987 
988  (void)cls;
989  (void)result;
990  (void)payload;
991  (void)physical;
992  n = lookup_neighbour(target);
993  if (NULL == n)
994  return; /* already gone */
996  return; /* have created a fresh entry since */
997  if (NULL != n->task)
1000 }
1001 
1002 
1008 static void
1010 {
1011  struct GNUNET_ATS_SessionDisconnectMessage disconnect_msg;
1012 
1014  "Sending DISCONNECT message to peer `%4s'\n",
1015  GNUNET_i2s(&n->id));
1016  disconnect_msg.header.size = htons(sizeof(struct GNUNET_ATS_SessionDisconnectMessage));
1017  disconnect_msg.header.type =
1019  disconnect_msg.reserved = htonl(0);
1020  disconnect_msg.purpose.size =
1021  htonl(sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) +
1022  sizeof(struct GNUNET_CRYPTO_EddsaPublicKey) +
1023  sizeof(struct GNUNET_TIME_AbsoluteNBO));
1024  disconnect_msg.purpose.purpose =
1026  disconnect_msg.timestamp =
1028  disconnect_msg.public_key = GST_my_identity.public_key;
1031  &disconnect_msg.purpose,
1032  &disconnect_msg.signature));
1033 
1034  (void)send_with_session(n,
1035  &disconnect_msg,
1036  sizeof(disconnect_msg),
1037  UINT32_MAX,
1039  GNUNET_NO,
1041  NULL);
1043  gettext_noop("# DISCONNECT messages sent"),
1044  1,
1045  GNUNET_NO);
1046 }
1047 
1048 
1054 static void
1056 {
1058  "Disconnecting from peer %s in state %s\n",
1059  GNUNET_i2s(&n->id),
1061  /* depending on state, notify neighbour and/or upper layers of this peer
1062  about disconnect */
1063  switch (n->state)
1064  {
1067  /* other peer is completely unaware of us, no need to send DISCONNECT */
1068  free_neighbour(n);
1069  return;
1070 
1072  send_disconnect(n);
1076  break;
1077 
1079  /* we never ACK'ed the other peer's request, no need to send DISCONNECT */
1080  free_neighbour(n);
1081  return;
1082 
1084  /* we DID ACK the other peer's request, must send DISCONNECT */
1085  send_disconnect(n);
1089  break;
1090 
1094  /* we are currently connected, need to send disconnect and do
1095  internal notifications and update statistics */
1096  send_disconnect(n);
1100  break;
1101 
1103  /* Disconnecting while waiting for an ATS address to reconnect,
1104  * cannot send DISCONNECT */
1105  free_neighbour(n);
1106  return;
1107 
1109  /* already disconnected, ignore */
1110  break;
1111 
1113  /* already cleaned up, how did we get here!? */
1114  GNUNET_assert(0);
1115  break;
1116 
1117  default:
1119  "Unhandled state `%s'\n",
1121  GNUNET_break(0);
1122  break;
1123  }
1124  /* schedule timeout to clean up */
1125  if (NULL != n->task)
1128  &master_task,
1129  n);
1130 }
1131 
1132 
1143 static int
1146 {
1148  "Setting inbound quota of %u Bps for peer `%s' to all clients\n",
1149  ntohl(quota.value__), GNUNET_i2s(&n->id));
1151  quota);
1152  if (0 != ntohl(quota.value__))
1153  {
1154  struct GNUNET_ATS_SessionQuotaMessage sqm;
1155 
1156  sqm.header.size = htons(sizeof(struct GNUNET_ATS_SessionQuotaMessage));
1158  sqm.quota = quota.value__;
1159  if (NULL != n->primary_address.session)
1160  (void)send_with_session(n,
1161  &sqm,
1162  sizeof(sqm),
1163  UINT32_MAX - 1,
1165  GNUNET_NO,
1166  NULL, NULL);
1167  return GNUNET_YES;
1168  }
1170  "Disconnecting peer `%s' due to SET_QUOTA\n",
1171  GNUNET_i2s(&n->id));
1172  if (GNUNET_YES == test_connected(n))
1174  gettext_noop("# disconnects due to quota of 0"),
1175  1, GNUNET_NO);
1177  return GNUNET_NO;
1178 }
1179 
1180 
1192 static void
1194  const struct GNUNET_HELLO_Address *address,
1195  struct GNUNET_ATS_Session *session,
1196  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
1197  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
1198 {
1199  if (session == n->primary_address.session)
1200  {
1202  GNUNET_YES);
1203  if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__)
1204  {
1205  n->primary_address.bandwidth_in = bandwidth_in;
1206  if (GNUNET_YES !=
1208  bandwidth_in))
1209  return;
1210  }
1211  if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__)
1212  {
1213  n->primary_address.bandwidth_out = bandwidth_out;
1215  }
1216  return;
1217  }
1218  if ((NULL != n->primary_address.address) &&
1219  (0 == GNUNET_HELLO_address_cmp(address,
1220  n->primary_address.address)))
1221  {
1222  GNUNET_break(0);
1223  return;
1224  }
1225  if (NULL == session)
1226  {
1227  GNUNET_break(0);
1228  GST_ats_block_address(address,
1229  session);
1230  return;
1231  }
1232  if (NULL != n->primary_address.address)
1233  {
1235  "Replacing existing primary address with another one\n");
1237  }
1239  n->primary_address.bandwidth_in = bandwidth_in;
1240  n->primary_address.bandwidth_out = bandwidth_out;
1241  n->primary_address.session = session;
1245  n->primary_address.session));
1246  /* subsystems about address use */
1248  GNUNET_YES);
1249  if (GNUNET_YES !=
1251  bandwidth_in))
1252  return;
1255  "Neighbour `%s' switched to address `%s'\n",
1256  GNUNET_i2s(&n->id),
1257  GST_plugins_a2s(address));
1258 
1261  n->state,
1262  n->timeout,
1265 }
1266 
1267 
1277 static void
1279  const struct GNUNET_PeerIdentity *receiver,
1280  int success,
1281  size_t size_payload,
1282  size_t physical)
1283 {
1284  struct MessageQueue *mq = cls;
1285  struct NeighbourMapEntry *n;
1286 
1287  if (NULL == (n = lookup_neighbour(receiver)))
1288  {
1289  if (NULL != mq->cont)
1290  mq->cont(mq->cont_cls,
1291  GNUNET_SYSERR /* not connected */,
1292  size_payload,
1293  0);
1294  GNUNET_free(mq);
1295  return; /* disconnect or other error while transmitting, can happen */
1296  }
1297  if (n->is_active == mq)
1298  {
1299  /* this is still "our" neighbour, remove us from its queue
1300  and allow it to send the next message now */
1301  n->is_active = NULL;
1302  if (NULL != n->task)
1305  n);
1306  }
1307  if (bytes_in_send_queue < mq->message_buf_size)
1308  {
1310  "Bytes_in_send_queue `%llu', Message_size %u, result: %s, payload %u, on wire %u\n",
1312  (unsigned int)mq->message_buf_size,
1313  (GNUNET_OK == success) ? "OK" : "FAIL",
1314  (unsigned int)size_payload,
1315  (unsigned int)physical);
1316  GNUNET_break(0);
1317  }
1318 
1319  GNUNET_break(size_payload == mq->message_buf_size);
1322  gettext_noop("# bytes in message queue for other peers"),
1324  GNUNET_NO);
1325  if (GNUNET_OK == success)
1327  gettext_noop("# messages transmitted to other peers"),
1328  1,
1329  GNUNET_NO);
1330  else
1332  gettext_noop
1333  ("# transmission failures for messages to other peers"),
1334  1, GNUNET_NO);
1336  "Sending message to `%s' of type %u with %u bytes was a %s\n",
1337  GNUNET_i2s(receiver),
1338  ntohs(((struct GNUNET_MessageHeader *)mq->message_buf)->type),
1339  (unsigned int)mq->message_buf_size,
1340  (success == GNUNET_OK) ? "success" : "FAILURE");
1341  if (NULL != mq->cont)
1342  mq->cont(mq->cont_cls,
1343  success,
1344  size_payload,
1345  physical);
1346  GNUNET_free(mq);
1347 }
1348 
1349 
1361 static void
1363 {
1364  struct MessageQueue *mq;
1365  struct GNUNET_TIME_Relative timeout;
1366 
1367  if (NULL == n->primary_address.address)
1368  {
1369  /* no address, why are we here? */
1370  GNUNET_break(0);
1371  return;
1372  }
1373  if ((0 == n->primary_address.address->address_length) &&
1374  (NULL == n->primary_address.session))
1375  {
1376  /* no address, why are we here? */
1377  GNUNET_break(0);
1378  return;
1379  }
1380  if (NULL != n->is_active)
1381  {
1382  /* transmission already pending */
1383  return;
1384  }
1385 
1386  /* timeout messages from the queue that are past their due date */
1387  while (NULL != (mq = n->messages_head))
1388  {
1390  if (timeout.rel_value_us > 0)
1391  break;
1393  gettext_noop("# messages timed out while in transport queue"),
1394  1,
1395  GNUNET_NO);
1397  n->messages_tail,
1398  mq);
1399  n->is_active = mq;
1401  &n->id,
1402  GNUNET_SYSERR,
1403  mq->message_buf_size,
1404  0); /* timeout */
1405  }
1406  if (NULL == mq)
1407  return; /* no more messages */
1408  if (NULL == n->primary_address.address)
1409  {
1410  /* transmit_send_continuation() caused us to drop session,
1411  can't try transmission anymore. */
1412  return;
1413  }
1414 
1415 
1417  n->messages_tail,
1418  mq);
1419  n->is_active = mq;
1420 
1422  "Giving message with %u bytes to plugin session %p\n",
1423  (unsigned int)mq->message_buf_size,
1425  (void)send_with_session(n,
1426  mq->message_buf,
1427  mq->message_buf_size,
1428  0 /* priority */,
1429  timeout,
1430  GNUNET_NO,
1432  mq);
1433 }
1434 
1435 
1444 static void
1446 {
1448  struct GNUNET_TIME_Relative timeout;
1449  uint32_t nonce;
1450 
1454  return; /* no keepalive needed at this time */
1455 
1456  nonce = 0; /* 0 indicates 'not set' */
1457  while (0 == nonce)
1459  UINT32_MAX);
1460 
1462  "Sending KEEPALIVE to peer `%s' with nonce %u\n",
1463  GNUNET_i2s(&n->id),
1464  nonce);
1465  m.header.size = htons(sizeof(struct GNUNET_ATS_SessionKeepAliveMessage));
1467  m.nonce = htonl(nonce);
1468 
1469  timeout = send_with_session(n,
1470  &m,
1471  sizeof(m),
1472  UINT32_MAX /* priority */,
1474  GNUNET_YES,
1475  NULL, NULL);
1477  gettext_noop("# KEEPALIVES sent"),
1478  1,
1479  GNUNET_NO);
1480  n->primary_address.keep_alive_nonce = nonce;
1484 }
1485 
1486 
1494 void
1496  const struct GNUNET_MessageHeader *m)
1497 {
1498  struct NeighbourMapEntry *n;
1499  const struct GNUNET_ATS_SessionKeepAliveMessage *msg_in;
1501 
1502  if (sizeof(struct GNUNET_ATS_SessionKeepAliveMessage) != ntohs(m->size))
1503  {
1504  GNUNET_break_op(0);
1505  return;
1506  }
1507 
1508  msg_in = (const struct GNUNET_ATS_SessionKeepAliveMessage *)m;
1509  if (NULL == (n = lookup_neighbour(neighbour)))
1510  {
1512  gettext_noop
1513  ("# KEEPALIVE messages discarded (peer unknown)"),
1514  1, GNUNET_NO);
1515  return;
1516  }
1517  if (NULL == n->primary_address.session)
1518  {
1520  gettext_noop
1521  ("# KEEPALIVE messages discarded (no session)"),
1522  1, GNUNET_NO);
1523  return;
1524  }
1525 
1527  "Received KEEPALIVE request from peer `%s' with nonce %u\n",
1528  GNUNET_i2s(&n->id),
1529  ntohl(msg_in->nonce));
1531  gettext_noop("# KEEPALIVES received in good order"),
1532  1,
1533  GNUNET_NO);
1534 
1535  /* send reply to allow neighbour to measure latency */
1536  msg.header.size = htons(sizeof(struct GNUNET_ATS_SessionKeepAliveMessage));
1538  msg.nonce = msg_in->nonce;
1539  (void)send_with_session(n,
1540  &msg,
1541  sizeof(struct GNUNET_ATS_SessionKeepAliveMessage),
1542  UINT32_MAX /* priority */,
1544  GNUNET_YES,
1545  NULL, NULL);
1546 }
1547 
1548 
1557 void
1559  const struct GNUNET_MessageHeader *m)
1560 {
1561  struct NeighbourMapEntry *n;
1563  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1564  struct GNUNET_TIME_Relative latency;
1565 
1566  if (sizeof(struct GNUNET_ATS_SessionKeepAliveMessage) != ntohs(m->size))
1567  {
1568  GNUNET_break_op(0);
1569  return;
1570  }
1571 
1572  msg = (const struct GNUNET_ATS_SessionKeepAliveMessage *)m;
1573  if (NULL == (n = lookup_neighbour(neighbour)))
1574  {
1576  gettext_noop("# KEEPALIVE_RESPONSEs discarded (not connected)"),
1577  1,
1578  GNUNET_NO);
1579  return;
1580  }
1581  if ((GNUNET_TRANSPORT_PS_CONNECTED != n->state) ||
1583  {
1585  gettext_noop("# KEEPALIVE_RESPONSEs discarded (not expected)"),
1586  1,
1587  GNUNET_NO);
1588  return;
1589  }
1590  if (NULL == n->primary_address.address)
1591  {
1593  gettext_noop("# KEEPALIVE_RESPONSEs discarded (address changed)"),
1594  1,
1595  GNUNET_NO);
1596  return;
1597  }
1598  if (n->primary_address.keep_alive_nonce != ntohl(msg->nonce))
1599  {
1600  if (0 == n->primary_address.keep_alive_nonce)
1602  gettext_noop("# KEEPALIVE_RESPONSEs discarded (no nonce)"),
1603  1,
1604  GNUNET_NO);
1605  else
1607  gettext_noop("# KEEPALIVE_RESPONSEs discarded (bad nonce)"),
1608  1,
1609  GNUNET_NO);
1610  return;
1611  }
1613  gettext_noop("# KEEPALIVE_RESPONSEs received (OK)"),
1614  1,
1615  GNUNET_NO);
1616 
1617 
1618  /* Update session timeout here */
1619  if (NULL != (papi = GST_plugins_find(n->primary_address.address->transport_name)))
1620  {
1622  "Updating session for peer `%s' for session %p\n",
1623  GNUNET_i2s(&n->id),
1625  papi->update_session_timeout(papi->cls,
1626  &n->id,
1628  }
1629  else
1630  {
1631  GNUNET_break(0);
1632  }
1633 
1637  n->state,
1639 
1642  "Received KEEPALIVE_RESPONSE from peer `%s', latency is %s\n",
1643  GNUNET_i2s(&n->id),
1645  GNUNET_YES));
1648  2));
1649 }
1650 
1651 
1664 struct GNUNET_TIME_Relative
1666  ssize_t size,
1667  int *do_forward)
1668 {
1669  struct NeighbourMapEntry *n;
1670  struct GNUNET_TIME_Relative ret;
1671 
1672  if (NULL == neighbours)
1673  {
1674  *do_forward = GNUNET_NO;
1675  return GNUNET_TIME_UNIT_FOREVER_REL; /* This can happen during shutdown */
1676  }
1677  if (NULL == (n = lookup_neighbour(sender)))
1678  {
1680  gettext_noop("# messages discarded due to lack of neighbour record"),
1681  1,
1682  GNUNET_NO);
1683  *do_forward = GNUNET_NO;
1684  return GNUNET_TIME_UNIT_ZERO;
1685  }
1686  if (!test_connected(n))
1687  {
1688  *do_forward = GNUNET_SYSERR;
1689  return GNUNET_TIME_UNIT_ZERO;
1690  }
1692  {
1693  n->quota_violation_count++;
1695  "Bandwidth quota (%u b/s) violation detected (total of %u).\n",
1698  /* Discount 32k per violation */
1700  }
1701  else
1702  {
1703  if (n->quota_violation_count > 0)
1704  {
1705  /* try to add 32k back */
1707  n->quota_violation_count--;
1708  }
1709  }
1711  {
1713  gettext_noop
1714  ("# bandwidth quota violations by other peers"),
1715  1, GNUNET_NO);
1716  *do_forward = GNUNET_NO;
1718  }
1719  *do_forward = GNUNET_YES;
1720  ret = GNUNET_BANDWIDTH_tracker_get_delay(&n->in_tracker, 32 * 1024);
1721  if (ret.rel_value_us > 0)
1722  {
1724  "Throttling read (%lld bytes excess at %u b/s), waiting %s before reading more.\n",
1726  (unsigned int)n->in_tracker.available_bytes_per_s__,
1729  gettext_noop("# ms throttling suggested"),
1730  (int64_t)ret.rel_value_us / 1000LL,
1731  GNUNET_NO);
1732  }
1733  return ret;
1734 }
1735 
1736 
1747 void
1749  const void *msg,
1750  size_t msg_size,
1751  struct GNUNET_TIME_Relative timeout,
1753  void *cont_cls)
1754 {
1755  struct NeighbourMapEntry *n;
1756  struct MessageQueue *mq;
1757 
1758  /* All ove these cases should never happen; they are all API violations.
1759  But we check anyway, just to be sure. */
1760  if (NULL == (n = lookup_neighbour(target)))
1761  {
1762  GNUNET_break(0);
1763  if (NULL != cont)
1764  cont(cont_cls,
1765  GNUNET_SYSERR,
1766  msg_size,
1767  0);
1768  return;
1769  }
1770  if (GNUNET_YES != test_connected(n))
1771  {
1772  GNUNET_break(0);
1773  if (NULL != cont)
1774  cont(cont_cls,
1775  GNUNET_SYSERR,
1776  msg_size,
1777  0);
1778  return;
1779  }
1780  bytes_in_send_queue += msg_size;
1782  gettext_noop
1783  ("# bytes in message queue for other peers"),
1785  mq = GNUNET_malloc(sizeof(struct MessageQueue) + msg_size);
1786  mq->cont = cont;
1787  mq->cont_cls = cont_cls;
1788  GNUNET_memcpy(&mq[1], msg, msg_size);
1789  mq->message_buf = (const char *)&mq[1];
1790  mq->message_buf_size = msg_size;
1792 
1794  "Enqueueing %u bytes to send to peer %s\n",
1795  (unsigned int)msg_size,
1796  GNUNET_i2s(target));
1798  n->messages_tail,
1799  mq);
1800  if (NULL != n->task)
1803 }
1804 
1805 
1818 static void
1820  const struct GNUNET_PeerIdentity *target,
1821  int result,
1822  size_t size_payload,
1823  size_t size_on_wire)
1824 {
1825  struct NeighbourMapEntry *n;
1826 
1827  (void)cls;
1828  (void)size_payload;
1829  (void)size_on_wire;
1830  n = lookup_neighbour(target);
1831  if (NULL == n)
1832  {
1833  /* SYN continuation was called after neighbor was freed,
1834  * for example due to a time out for the state or the session
1835  * used was already terminated: nothing to do here... */
1836  return;
1837  }
1838 
1839  if ((GNUNET_TRANSPORT_PS_SYN_SENT != n->state) &&
1842  {
1843  /* SYN continuation was called after neighbor changed state,
1844  * for example due to a time out for the state or the session
1845  * used was already terminated: nothing to do here... */
1846  return;
1847  }
1848  if (GNUNET_OK == result)
1849  return;
1850 
1852  _("Failed to send SYN message to peer `%s'\n"),
1853  GNUNET_i2s(target));
1854  switch (n->state)
1855  {
1857  /* Remove address and request an additional one */
1862  break;
1863 
1865  /* Remove address and request an additional one */
1870  break;
1871 
1873  /* Remove address and request and go back to primary address */
1875  gettext_noop("# Failed attempts to switch addresses (failed to send SYN CONT)"),
1876  1,
1877  GNUNET_NO);
1879  "Switch failed, cleaning up alternative address\n");
1884  break;
1885 
1886  default:
1888  break;
1889  }
1890 }
1891 
1892 
1898 static void
1900 {
1901  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1902  struct TransportSynMessage connect_msg;
1903  struct NeighbourMapEntry *n;
1904 
1905  GNUNET_assert(NULL != na->session);
1907  "Sending SYN message to peer `%s' at %s\n",
1908  GNUNET_i2s(&na->address->peer),
1909  GST_plugins_a2s(na->address));
1910 
1912  GNUNET_assert(NULL != papi);
1914  gettext_noop
1915  ("# SYN messages sent"),
1916  1, GNUNET_NO);
1918  connect_msg.header.size = htons(sizeof(struct TransportSynMessage));
1920  connect_msg.reserved = htonl(0);
1922  if (-1 ==
1923  papi->send(papi->cls,
1924  na->session,
1925  (const char *)&connect_msg,
1926  sizeof(struct TransportSynMessage),
1927  UINT_MAX,
1929  &send_session_syn_cont, NULL))
1930  {
1932  _("Failed to transmit SYN message to %s\n"),
1933  GST_plugins_a2s(na->address));
1934  n = lookup_neighbour(&na->address->peer);
1935  if (NULL == n)
1936  {
1937  GNUNET_break(0);
1938  return;
1939  }
1940  switch (n->state)
1941  {
1943  /* Remove address and request and additional one */
1944  GNUNET_assert(na == &n->primary_address);
1949  /* Hard failure to send the SYN message with this address:
1950  Destroy address and session */
1951  break;
1952 
1954  /* Remove address and request an additional one */
1955  GNUNET_assert(na == &n->primary_address);
1960  break;
1961 
1965  gettext_noop("# Failed attempts to switch addresses (failed to send SYN)"),
1966  1,
1967  GNUNET_NO);
1968  /* Remove address and request an additional one */
1970  "Switch failed, cleaning up alternative address\n");
1975  break;
1976 
1977  default:
1978  GNUNET_break(0);
1980  break;
1981  }
1982  return;
1983  }
1985  na->session,
1986  sizeof(struct TransportSynMessage));
1987 }
1988 
1989 
2002 static void
2004  const struct GNUNET_PeerIdentity *target,
2005  int result,
2006  size_t size_payload,
2007  size_t size_on_wire)
2008 {
2009  struct NeighbourMapEntry *n;
2010 
2011  (void)cls;
2012  (void)size_payload;
2013  (void)size_on_wire;
2014  n = lookup_neighbour(target);
2015  if (NULL == n)
2016  {
2017  /* SYN_ACK continuation was called after neighbor was freed,
2018  * for example due to a time out for the state or the session
2019  * used was already terminated: nothing to do here... */
2020  return;
2021  }
2022 
2024  {
2025  /* SYN_ACK continuation was called after neighbor changed state,
2026  * for example due to a time out for the state or the session
2027  * used was already terminated: nothing to do here... */
2028  return;
2029  }
2030  if (GNUNET_OK == result)
2031  return;
2032 
2034  _("Failed to send SYN_ACK message to peer `%s' using address `%s'\n"),
2035  GNUNET_i2s(target),
2037 
2038  /* Remove address and request and additional one */
2039  /* FIXME: what if the neighbour's primary address
2040  changed in the meantime? Might want to instead
2041  pass "something" around in closure to be sure. */
2047 }
2048 
2049 
2057 static void
2059  struct GNUNET_TIME_Absolute timestamp)
2060 {
2061  const struct GNUNET_HELLO_Address *address = na->address;
2062  struct GNUNET_ATS_Session *session = na->session;
2063  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2064  struct TransportSynMessage connect_msg;
2065  struct NeighbourMapEntry *n;
2066 
2068  "Sending SYN_ACK to peer `%s'\n",
2069  GNUNET_i2s(&address->peer));
2070 
2071  if (NULL == (papi = GST_plugins_find(address->transport_name)))
2072  {
2073  GNUNET_break(0);
2074  return;
2075  }
2076  if (NULL == session)
2077  session = papi->get_session(papi->cls,
2078  address);
2079  if (NULL == session)
2080  {
2081  GNUNET_break(0);
2082  return;
2083  }
2084  GST_ats_new_session(address,
2085  session);
2087  gettext_noop
2088  ("# SYN_ACK messages sent"),
2089  1, GNUNET_NO);
2090  connect_msg.header.size = htons(sizeof(struct TransportSynMessage));
2092  connect_msg.reserved = htonl(0);
2093  connect_msg.timestamp = GNUNET_TIME_absolute_hton(timestamp);
2094 
2095  if (GNUNET_SYSERR ==
2096  papi->send(papi->cls,
2097  session,
2098  (const char *)&connect_msg,
2099  sizeof(struct TransportSynMessage),
2100  UINT_MAX,
2102  &send_session_syn_ack_cont, NULL))
2103  {
2105  _("Failed to transmit SYN_ACK message to %s\n"),
2106  GST_plugins_a2s(address));
2107 
2108  n = lookup_neighbour(&address->peer);
2109  if (NULL == n)
2110  {
2111  GNUNET_break(0);
2112  return;
2113  }
2114  /* Remove address and request and additional one */
2120  return;
2121  }
2122 }
2123 
2124 
2133 static void
2135 {
2136  struct NeighbourMapEntry *n = cls;
2137  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2138  struct GNUNET_TIME_Relative delay;
2139  int do_forward;
2140 
2141  if (NULL == n->primary_address.address)
2142  return; /* not active, ignore */
2144  GNUNET_assert(NULL != papi);
2145  if (NULL == papi->update_inbound_delay)
2146  return;
2148  0,
2149  &do_forward);
2151  "New inbound delay for peer `%s' is %llu ms\n",
2152  GNUNET_i2s(&n->id),
2153  (unsigned long long)delay.rel_value_us / 1000LL);
2154  if (NULL == n->primary_address.session)
2155  return;
2156  papi->update_inbound_delay(papi->cls,
2157  &n->id,
2159  delay);
2160 }
2161 
2162 
2169 static struct NeighbourMapEntry *
2171 {
2172  struct NeighbourMapEntry *n;
2173 
2174  if (0 ==
2175  memcmp(&GST_my_identity,
2176  peer,
2177  sizeof(struct GNUNET_PeerIdentity)))
2178  {
2180  "Cowardly refusing to consider myself my neighbour!\n");
2181  return NULL;
2182  }
2184  "Creating new neighbour entry for `%s'\n",
2185  GNUNET_i2s(peer));
2186  n = GNUNET_new(struct NeighbourMapEntry);
2187  n->id = *peer;
2188  n->ack_state = ACK_UNDEFINED;
2193  n,
2202  &n->id,
2203  n,
2206  peer,
2207  0);
2208 
2209  return n;
2210 }
2211 
2212 
2221 
2226 
2231 
2235  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
2236 
2240  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
2241 };
2242 
2243 
2252 int
2254  const struct GNUNET_PeerIdentity *peer)
2255 {
2256  const struct TransportSynMessage *scm;
2257  struct NeighbourMapEntry *n;
2258  struct GNUNET_TIME_Absolute ts;
2259 
2260  if (ntohs(message->size) != sizeof(struct TransportSynMessage))
2261  {
2262  GNUNET_break_op(0);
2263  return GNUNET_SYSERR;
2264  }
2266  gettext_noop
2267  ("# SYN messages received"),
2268  1, GNUNET_NO);
2269  if (NULL == neighbours)
2270  {
2272  _("SYN request from peer `%s' ignored due impending shutdown\n"),
2273  GNUNET_i2s(peer));
2274  return GNUNET_OK; /* we're shutting down */
2275  }
2276  scm = (const struct TransportSynMessage *)message;
2277  GNUNET_break_op(0 == ntohl(scm->reserved));
2279  if (0 ==
2280  memcmp(&GST_my_identity,
2281  peer,
2282  sizeof(struct GNUNET_PeerIdentity)))
2283  {
2284  /* loopback connection-to-self, ignore */
2285  return GNUNET_SYSERR;
2286  }
2287  n = lookup_neighbour(peer);
2288  if (NULL == n)
2289  {
2290  /* This is a new neighbour and set to not connected */
2291  n = setup_neighbour(peer);
2292  GNUNET_assert(NULL != n);
2293  }
2294 
2295  /* Remember this SYN message in neighbour */
2297  n->connect_ack_timestamp = ts;
2298 
2300  "Received SYN for peer `%s' in state %s/%s\n",
2301  GNUNET_i2s(peer),
2304 
2305  switch (n->state)
2306  {
2308  /* Request an address from ATS to send SYN_ACK to this peer */
2312  break;
2313 
2315  /* SYN message takes priority over us asking ATS for address:
2316  * Wait for ATS to suggest an address and send SYN_ACK */
2320  break;
2321 
2323  /* We already wait for an address to send an SYN_ACK */
2324  break;
2325 
2328  /* Send ACK immediately */
2329  n->ack_state = ACK_SEND_ACK;
2331  ts);
2332  break;
2333 
2335  /* we are already connected and can thus send the ACK immediately */
2338  n->ack_state = ACK_SEND_ACK;
2340  ts);
2341  break;
2342 
2344  /* We wait for ATS address suggestion */
2345  break;
2346 
2348  /* We received a SYN message while waiting for a SYN_ACK in fast
2349  * reconnect. Send SYN_ACK immediately */
2350  n->ack_state = ACK_SEND_ACK;
2353  break;
2354 
2356  /* We are already connected and can thus send the ACK immediately;
2357  still, it can never hurt to have an alternative address, so also
2358  tell ATS about it */
2361  n->ack_state = ACK_SEND_ACK;
2363  ts);
2364  break;
2365 
2367  /* Get rid of remains and re-try */
2368  free_neighbour(n);
2369  n = setup_neighbour(peer);
2370  GNUNET_assert(NULL != n);
2371  /* Remember the SYN time stamp for ACK message */
2373  n->connect_ack_timestamp = ts;
2374  /* Request an address for the peer */
2378  break;
2379 
2381  /* should not be possible */
2382  GNUNET_assert(0);
2383  break;
2384 
2385  default:
2387  "Unhandled state `%s'\n",
2389  GNUNET_break(0);
2390  return GNUNET_SYSERR;
2391  }
2392  return GNUNET_OK;
2393 }
2394 
2395 
2412 static int
2414  struct GNUNET_ATS_Session *session,
2415  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
2416  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
2417 {
2418  struct NeighbourMapEntry *n;
2419 
2420  n = lookup_neighbour(&address->peer);
2421  if ((NULL == n) ||
2422  (NULL == n->primary_address.address) ||
2423  (0 != GNUNET_HELLO_address_cmp(address,
2424  n->primary_address.address)))
2425  return GNUNET_NO;
2426  /* We are not really switching addresses, but merely adjusting
2427  session and/or bandwidth, can do fast ATS update! */
2428  if (session != n->primary_address.session)
2429  {
2430  /* switch to a different session, but keeping same address; could
2431  happen if there is a 2nd inbound connection */
2432  n->primary_address.session = session;
2435  n->primary_address.session));
2436  }
2437  if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__)
2438  {
2439  n->primary_address.bandwidth_in = bandwidth_in;
2440  if (GNUNET_YES !=
2442  bandwidth_in))
2443  return GNUNET_NO;
2444  }
2445  if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__)
2446  {
2447  n->primary_address.bandwidth_out = bandwidth_out;
2449  }
2450  return GNUNET_OK;
2451 }
2452 
2453 
2467 static void
2469  const struct GNUNET_PeerIdentity *peer,
2470  const struct GNUNET_HELLO_Address *address,
2471  struct GNUNET_ATS_Session *session,
2472  int result)
2473 {
2474  struct BlacklistCheckSwitchContext *blc_ctx = cls;
2475  struct GNUNET_TRANSPORT_PluginFunctions *papi;
2476  struct NeighbourMapEntry *n;
2477 
2478  if (GNUNET_SYSERR == result)
2479  goto cleanup;
2480 
2481  papi = GST_plugins_find(address->transport_name);
2482  if (NULL == papi)
2483  {
2484  /* This can happen during shutdown. */
2485  goto cleanup;
2486  }
2487 
2488  if (GNUNET_NO == result)
2489  {
2491  "Blacklist denied to switch to suggested address `%s' session %p for peer `%s'\n",
2492  GST_plugins_a2s(address),
2493  session,
2494  GNUNET_i2s(peer));
2496  "# ATS suggestions ignored (blacklist denied)",
2497  1,
2498  GNUNET_NO);
2499  if (NULL != session)
2500  papi->disconnect_session(papi->cls,
2501  session);
2502  if (GNUNET_YES !=
2505  GST_ats_block_address(address,
2506  NULL);
2507  goto cleanup;
2508  }
2509 
2510 
2511  if (NULL == session)
2512  {
2513  /* need to create a session, ATS only gave us an address */
2514  session = papi->get_session(papi->cls,
2515  address);
2517  "Obtained new session for peer `%s' and address '%s': %p\n",
2518  GNUNET_i2s(&address->peer),
2519  GST_plugins_a2s(address),
2520  session);
2521  if (NULL != session)
2522  GST_ats_new_session(address,
2523  session);
2524  }
2525  if (NULL == session)
2526  {
2527  /* session creation failed, bad!, fail! */
2529  "# ATS suggestions ignored (failed to create session)",
2530  1,
2531  GNUNET_NO);
2532  /* No session could be obtained, remove blacklist check and clean up */
2534  "Failed to obtain new session for peer `%s' and address '%s'\n",
2535  GNUNET_i2s(&address->peer),
2536  GST_plugins_a2s(address));
2537  GST_ats_block_address(address,
2538  session);
2539  goto cleanup;
2540  }
2541 
2542  /* We did this check already before going into blacklist, but
2543  it is theoretically possible that the situation changed in
2544  the meantime, hence we check again here */
2545  if (GNUNET_OK ==
2546  try_run_fast_ats_update(address,
2547  session,
2548  blc_ctx->bandwidth_in,
2549  blc_ctx->bandwidth_out))
2550  goto cleanup; /* was just a minor update, we're done */
2551 
2552  /* check if we also need to setup the neighbour entry */
2553  if (NULL == (n = lookup_neighbour(peer)))
2554  {
2555  n = setup_neighbour(peer);
2556  if (NULL == n)
2557  {
2558  /* not sure how this can happen... */
2559  GNUNET_break(0);
2560  goto cleanup;
2561  }
2563  }
2564 
2566  "Peer `%s' switches to address `%s'\n",
2567  GNUNET_i2s(&address->peer),
2568  GST_plugins_a2s(address));
2569 
2570  switch (n->state)
2571  {
2573  GNUNET_break(0);
2574  GST_ats_block_address(address,
2575  session);
2576  free_neighbour(n);
2577  return;
2578 
2580  /* We requested an address and ATS suggests one:
2581  * set primary address and send SYN message*/
2583  address,
2584  session,
2585  blc_ctx->bandwidth_in,
2586  blc_ctx->bandwidth_out);
2587  if (ACK_SEND_SYN_ACK == n->ack_state)
2588  {
2589  /* Send pending SYN_ACK message */
2590  n->ack_state = ACK_SEND_ACK;
2593  }
2598  break;
2599 
2601  /* ATS suggested a new address while waiting for an SYN_ACK:
2602  * Switch and send new SYN */
2603  /* ATS suggests a different address, switch again */
2605  address,
2606  session,
2607  blc_ctx->bandwidth_in,
2608  blc_ctx->bandwidth_out);
2609  if (ACK_SEND_SYN_ACK == n->ack_state)
2610  {
2611  /* Send pending SYN_ACK message */
2612  n->ack_state = ACK_SEND_ACK;
2615  }
2620  break;
2621 
2623  /* We requested an address and ATS suggests one:
2624  * set primary address and send SYN_ACK message*/
2626  address,
2627  session,
2628  blc_ctx->bandwidth_in,
2629  blc_ctx->bandwidth_out);
2630  /* Send an ACK message as a response to the SYN msg */
2636  if ((ACK_SEND_SYN_ACK == n->ack_state) ||
2637  (ACK_UNDEFINED == n->ack_state))
2638  n->ack_state = ACK_SEND_ACK;
2639  break;
2640 
2642  /* ATS asks us to switch while we were trying to connect; switch to new
2643  address and check blacklist again */
2644  if ((ACK_SEND_SYN_ACK == n->ack_state))
2645  {
2646  n->ack_state = ACK_SEND_ACK;
2649  }
2651  address,
2652  session,
2653  blc_ctx->bandwidth_in,
2654  blc_ctx->bandwidth_out);
2658  break;
2659 
2663  GNUNET_break(n->primary_address.session != session);
2664  /* ATS asks us to switch a life connection; see if we can get
2665  a SYN_ACK on it before we actually do this! */
2667  address,
2668  session,
2669  blc_ctx->bandwidth_in,
2670  blc_ctx->bandwidth_out);
2675  gettext_noop("# Attempts to switch addresses"),
2676  1,
2677  GNUNET_NO);
2679  break;
2680 
2683  address,
2684  session,
2685  blc_ctx->bandwidth_in,
2686  blc_ctx->bandwidth_out);
2687  if (ACK_SEND_SYN_ACK == n->ack_state)
2688  {
2689  /* Send pending SYN_ACK message */
2690  n->ack_state = ACK_SEND_ACK;
2693  }
2698  break;
2699 
2701  /* ATS asks us to switch while we were trying to reconnect; switch to new
2702  address and send SYN again */
2704  address,
2705  session,
2706  blc_ctx->bandwidth_in,
2707  blc_ctx->bandwidth_out);
2712  break;
2713 
2716  address)) &&
2717  (n->primary_address.session == session))
2718  {
2719  /* ATS switches back to still-active session */
2721  "ATS double-switched, cleaning up alternative address\n");
2725  n->timeout);
2726  break;
2727  }
2728  /* ATS asks us to switch a life connection, send */
2730  address,
2731  session,
2732  blc_ctx->bandwidth_in,
2733  blc_ctx->bandwidth_out);
2738  break;
2739 
2741  /* not going to switch addresses while disconnecting */
2743  "# ATS suggestion ignored (disconnecting)",
2744  1,
2745  GNUNET_NO);
2746  return;
2747 
2749  GNUNET_assert(0);
2750  break;
2751 
2752  default:
2754  "Unhandled state `%s'\n",
2756  GNUNET_break(0);
2757  break;
2758  }
2759 cleanup:
2760  GNUNET_CONTAINER_DLL_remove(pending_bc_head,
2761  pending_bc_tail,
2762  blc_ctx);
2763  GNUNET_free(blc_ctx);
2764 }
2765 
2766 
2784 void
2786  struct GNUNET_ATS_Session *session,
2787  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
2788  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
2789 {
2790  struct GST_BlacklistCheck *blc;
2791  struct BlacklistCheckSwitchContext *blc_ctx;
2792 
2793  GNUNET_assert(NULL != address->transport_name);
2794  if (GNUNET_OK ==
2795  try_run_fast_ats_update(address,
2796  session,
2797  bandwidth_in,
2798  bandwidth_out))
2799  return;
2800 
2801  /* Check if plugin is available */
2802  if (NULL == (GST_plugins_find(address->transport_name)))
2803  {
2804  /* we don't have the plugin for this address */
2805  GNUNET_break(0);
2806  GST_ats_block_address(address,
2807  session);
2808  return;
2809  }
2810  if ((NULL == session) &&
2813  {
2814  /* This is a inbound address and we do not have a session to use! */
2815  GNUNET_break(0);
2816  GST_ats_block_address(address,
2817  session);
2818  return;
2819  }
2820 
2822  "ATS suggests address '%s' for peer `%s' at %u/%u speed\n",
2823  GST_plugins_a2s(address),
2824  GNUNET_i2s(&address->peer),
2825  (unsigned int)ntohl(bandwidth_in.value__),
2826  (unsigned int)ntohl(bandwidth_out.value__));
2827 
2828  /* Perform blacklist check */
2829  blc_ctx = GNUNET_new(struct BlacklistCheckSwitchContext);
2830  blc_ctx->bandwidth_in = bandwidth_in;
2831  blc_ctx->bandwidth_out = bandwidth_out;
2832  GNUNET_CONTAINER_DLL_insert(pending_bc_head,
2833  pending_bc_tail,
2834  blc_ctx);
2835  if (NULL != (blc = GST_blacklist_test_allowed(&address->peer,
2836  address->transport_name,
2838  blc_ctx,
2839  address,
2840  session)))
2841  {
2842  blc_ctx->blc = blc;
2843  }
2844 }
2845 
2846 
2856 static int
2858  const struct GNUNET_PeerIdentity *key,
2859  void *value)
2860 {
2861  struct NeighbourMapEntry *n = value;
2862  uint32_t bps_in;
2863  uint32_t bps_out;
2864  struct GNUNET_TIME_Relative delta;
2865 
2866  (void)cls;
2867  if ((GNUNET_YES != test_connected(n)) ||
2868  (NULL == n->primary_address.address))
2869  return GNUNET_OK;
2872  bps_in = 0;
2873  if ((0 != n->util_total_bytes_recv) && (0 != delta.rel_value_us))
2874  bps_in = (1000LL * 1000LL * n->util_total_bytes_recv) / (delta.rel_value_us);
2875  bps_out = 0;
2876  if ((0 != n->util_total_bytes_sent) && (0 != delta.rel_value_us))
2877  bps_out = (1000LL * 1000LL * n->util_total_bytes_sent) / delta.rel_value_us;
2878 
2880  "`%s' total: received %u Bytes/s, sent %u Bytes/s\n",
2881  GNUNET_i2s(key),
2882  bps_in,
2883  bps_out);
2885  bps_in,
2886  bps_out);
2887  n->util_total_bytes_recv = 0;
2888  n->util_total_bytes_sent = 0;
2890  return GNUNET_OK;
2891 }
2892 
2893 
2899 static void
2901 {
2902  (void)cls;
2903  util_transmission_tk = NULL;
2906  NULL);
2907  util_transmission_tk
2910  NULL);
2911 }
2912 
2913 
2922 void
2924  const struct GNUNET_MessageHeader *message)
2925 {
2926  struct NeighbourMapEntry *n;
2927 
2928  n = lookup_neighbour(&address->peer);
2929  if (NULL == n)
2930  return;
2931  n->util_total_bytes_recv += ntohs(message->size);
2932 }
2933 
2934 
2944 void
2946  struct GNUNET_ATS_Session *session,
2947  size_t size)
2948 {
2949  struct NeighbourMapEntry *n;
2950 
2951  n = lookup_neighbour(&address->peer);
2952  if (NULL == n)
2953  return;
2954  if (n->primary_address.session != session)
2955  return;
2957 }
2958 
2959 
2967 static void
2968 master_task(void *cls)
2969 {
2970  struct NeighbourMapEntry *n = cls;
2971  struct GNUNET_TIME_Relative delay;
2972 
2973  n->task = NULL;
2976  "Master task runs for neighbour `%s' in state %s with timeout in %s\n",
2977  GNUNET_i2s(&n->id),
2980  GNUNET_YES));
2981  switch (n->state)
2982  {
2984  /* invalid state for master task, clean up */
2985  GNUNET_break(0);
2986  free_neighbour(n);
2987  return;
2988 
2990  if (0 == delay.rel_value_us)
2991  {
2993  "Connection to `%s' timed out waiting for ATS to provide address\n",
2994  GNUNET_i2s(&n->id));
2995  free_neighbour(n);
2996  return;
2997  }
2998  break;
2999 
3001  if (0 == delay.rel_value_us)
3002  {
3004  "Connection to `%s' timed out waiting for other peer to send SYN_ACK\n",
3005  GNUNET_i2s(&n->id));
3006  /* Remove address and request and additional one */
3011  return;
3012  }
3013  break;
3014 
3016  if (0 == delay.rel_value_us)
3017  {
3019  "Connection to `%s' timed out waiting ATS to provide address to use for SYN_ACK\n",
3020  GNUNET_i2s(&n->id));
3021  free_neighbour(n);
3022  return;
3023  }
3024  break;
3025 
3027  if (0 == delay.rel_value_us)
3028  {
3030  "Connection to `%s' timed out waiting for other peer to send ACK\n",
3031  GNUNET_i2s(&n->id));
3033  return;
3034  }
3035  break;
3036 
3038  if (0 == delay.rel_value_us)
3039  {
3041  "Connection to `%s' timed out, missing KEEPALIVE_RESPONSEs\n",
3042  GNUNET_i2s(&n->id));
3044  return;
3045  }
3047  send_keepalive(n);
3048  break;
3049 
3051  if (0 == delay.rel_value_us)
3052  {
3054  "Connection to `%s' timed out, waiting for ATS replacement address\n",
3055  GNUNET_i2s(&n->id));
3057  return;
3058  }
3059  break;
3060 
3062  if (0 == delay.rel_value_us)
3063  {
3065  "Connection to `%s' timed out, waiting for other peer to SYN_ACK replacement address\n",
3066  GNUNET_i2s(&n->id));
3068  return;
3069  }
3070  break;
3071 
3073  if (0 == delay.rel_value_us)
3074  {
3076  "Switch failed, cleaning up alternative address\n");
3081  }
3083  send_keepalive(n);
3084  break;
3085 
3088  "Cleaning up connection to `%s' after sending DISCONNECT\n",
3089  GNUNET_i2s(&n->id));
3090  free_neighbour(n);
3091  return;
3092 
3094  /* how did we get here!? */
3095  GNUNET_assert(0);
3096  break;
3097 
3098  default:
3100  "Unhandled state `%s'\n",
3102  GNUNET_break(0);
3103  break;
3104  }
3108  {
3109  /* if we are *now* in one of the two states, we're sending
3110  keep alive messages, so we need to consider the keepalive
3111  delay, not just the connection timeout */
3113  delay);
3114  }
3115  if (NULL == n->task)
3117  &master_task,
3118  n);
3119 }
3120 
3121 
3128 static void
3130 {
3131  struct GNUNET_MessageHeader msg;
3132 
3134  "Sending ACK message to peer `%s'\n",
3135  GNUNET_i2s(&n->id));
3136 
3137  msg.size = htons(sizeof(struct GNUNET_MessageHeader));
3139  (void)send_with_session(n,
3140  &msg,
3141  sizeof(struct GNUNET_MessageHeader),
3142  UINT32_MAX,
3144  GNUNET_NO,
3145  NULL, NULL);
3146 }
3147 
3148 
3160 int
3162  const struct GNUNET_HELLO_Address *address,
3163  struct GNUNET_ATS_Session *session)
3164 {
3165  const struct TransportSynMessage *scm;
3166  struct GNUNET_TIME_Absolute ts;
3167  struct NeighbourMapEntry *n;
3168 
3169  (void)session;
3170  if (ntohs(message->size) != sizeof(struct TransportSynMessage))
3171  {
3172  GNUNET_break_op(0);
3173  return GNUNET_SYSERR;
3174  }
3176  gettext_noop
3177  ("# SYN_ACK messages received"),
3178  1, GNUNET_NO);
3179  scm = (const struct TransportSynMessage *)message;
3180  GNUNET_break_op(ntohl(scm->reserved) == 0);
3181  if (NULL == (n = lookup_neighbour(&address->peer)))
3182  {
3184  gettext_noop
3185  ("# unexpected SYN_ACK messages (no peer)"),
3186  1, GNUNET_NO);
3187  return GNUNET_SYSERR;
3188  }
3190  "Received SYN_ACK message from peer `%s' in state %s/%s\n",
3191  GNUNET_i2s(&address->peer),
3195  switch (n->state)
3196  {
3198  GNUNET_break(0);
3199  free_neighbour(n);
3200  return GNUNET_SYSERR;
3201 
3204  gettext_noop("# unexpected SYN_ACK messages (not ready)"),
3205  1,
3206  GNUNET_NO);
3207  break;
3208 
3211  {
3213  "SYN_ACK ignored as the timestamp does not match our SYN request\n");
3214  return GNUNET_OK;
3215  }
3225  break;
3226 
3230  gettext_noop("# unexpected SYN_ACK messages (not ready)"),
3231  1,
3232  GNUNET_NO);
3233  break;
3234 
3236  /* duplicate SYN_ACK, let's answer by duplicate ACK just in case */
3238  break;
3239 
3241  /* we didn't expect any SYN_ACK, as we are waiting for ATS
3242  to give us a new address... */
3244  gettext_noop("# unexpected SYN_ACK messages (waiting on ATS)"),
3245  1,
3246  GNUNET_NO);
3247  break;
3248 
3250  /* Reconnecting with new address address worked; go back to connected! */
3255  break;
3256 
3258  /* new address worked; adopt it and go back to connected! */
3263 
3264  /* Set primary addresses */
3271  gettext_noop("# Successful attempts to switch addresses"),
3272  1,
3273  GNUNET_NO);
3274 
3276  memset(&n->alternative_address,
3277  0,
3278  sizeof(n->alternative_address));
3280  break;
3281 
3284  gettext_noop
3285  ("# unexpected SYN_ACK messages (disconnecting)"),
3286  1, GNUNET_NO);
3287  return GNUNET_SYSERR;
3288 
3290  GNUNET_assert(0);
3291  break;
3292 
3293  default:
3295  "Unhandled state `%s'\n",
3297  GNUNET_break(0);
3298  return GNUNET_SYSERR;
3299  }
3300  return GNUNET_OK;
3301 }
3302 
3303 
3313 int
3315  struct GNUNET_ATS_Session *session)
3316 {
3317  struct NeighbourMapEntry *n;
3318 
3319  if (NULL == (n = lookup_neighbour(peer)))
3320  return GNUNET_NO; /* can't affect us */
3321  if (session != n->primary_address.session)
3322  {
3323  /* Free alternative address */
3324  if (session == n->alternative_address.session)
3325  {
3329  n->timeout);
3331  "Session died, cleaning up alternative address\n");
3333  }
3334  return GNUNET_NO; /* doesn't affect us further */
3335  }
3336 
3338  /* The session for neighbour's primary address died */
3339  switch (n->state)
3340  {
3342  GNUNET_break(0);
3343  free_neighbour(n);
3344  return GNUNET_YES;
3345 
3347  GNUNET_break(0);
3348  free_neighbour(n);
3349  return GNUNET_YES;
3350 
3352  /* The session used to send the SYN terminated:
3353  * this implies a connect error*/
3355  "Failed to send SYN in CONNECT_SENT with `%s' %p: session terminated\n",
3358 
3359  /* Destroy the address since it cannot be used */
3364  break;
3365 
3368  /* error on inbound session; free neighbour entirely */
3369  free_neighbour(n);
3370  return GNUNET_YES;
3371 
3373  /* Our primary connection died, try a fast reconnect */
3378  break;
3379 
3381  /* we don't have an address, how can it go down? */
3382  GNUNET_break(0);
3383  break;
3384 
3387  "Failed to send SYN in RECONNECT_SENT with `%s' %p: session terminated\n",
3390  /* Destroy the address since it cannot be used */
3395  break;
3396 
3398  /* primary went down while we were waiting for SYN_ACK on secondary;
3399  secondary as primary */
3400 
3402  "Connection `%s' %p to peer `%s' was terminated while switching, "
3403  "switching to alternative address `%s' %p\n",
3406  GNUNET_i2s(peer),
3409 
3410  /* Destroy the inbound address since it cannot be used */
3415  n->primary_address.session));
3416  memset(&n->alternative_address,
3417  0,
3418  sizeof(struct NeighbourAddress));
3422  break;
3423 
3426  break;
3427 
3429  /* neighbour was freed and plugins told to terminate session */
3430  return GNUNET_NO;
3431 
3432  default:
3434  "Unhandled state `%s'\n",
3436  GNUNET_break(0);
3437  break;
3438  }
3439  if (NULL != n->task)
3442  return GNUNET_YES;
3443 }
3444 
3445 
3456 int
3458  const struct GNUNET_HELLO_Address *address,
3459  struct GNUNET_ATS_Session *session)
3460 {
3461  struct NeighbourMapEntry *n;
3462 
3463  (void)session;
3464  if (ntohs(message->size) != sizeof(struct GNUNET_MessageHeader))
3465  {
3466  GNUNET_break_op(0);
3467  return GNUNET_SYSERR;
3468  }
3470  gettext_noop("# ACK messages received"),
3471  1,
3472  GNUNET_NO);
3473  if (NULL == (n = lookup_neighbour(&address->peer)))
3474  {
3475  GNUNET_break_op(0);
3476  return GNUNET_SYSERR;
3477  }
3479  "Received ACK for peer `%s' in state %s/%s\n",
3480  GNUNET_i2s(&address->peer),
3483 
3484  /* Check if we are in a plausible state for having sent
3485  a SYN_ACK. If not, return, otherwise break.
3486 
3487  The remote peers sends a ACK as a response for a SYN_ACK
3488  message.
3489 
3490  We expect a ACK:
3491  - If a remote peer has sent a SYN, we responded with a SYN_ACK and
3492  now wait for the ACK to finally be connected
3493  - If we sent a SYN_ACK to this peer before */
3494 
3495  if (((GNUNET_TRANSPORT_PS_SYN_RECV_ACK != n->state) &&
3496  (ACK_SEND_ACK != n->ack_state)) ||
3497  (NULL == n->primary_address.address))
3498  {
3500  "Received unexpected ACK message from peer `%s' in state %s/%s\n",
3501  GNUNET_i2s(&address->peer),
3504 
3506  gettext_noop("# unexpected ACK messages"),
3507  1,
3508  GNUNET_NO);
3509  return GNUNET_OK;
3510  }
3512  {
3513  /* We tried to switch addresses while being connect. We explicitly wait
3514  * for a SYN_ACK before going to GNUNET_TRANSPORT_PS_CONNECTED,
3515  * so we do not want to set the address as in use! */
3516  return GNUNET_OK;
3517  }
3521 
3522  if (NULL == n->primary_address.address)
3523  {
3524  /* See issue #3693.
3525  * We are in state = PSY_SYN_RECV_ACK or ack_state = ACK_SEND_ACK, which
3526  * really means we did try (and succeed) to send a SYN and are waiting for
3527  * an ACK.
3528  * That suggests that the primary_address used to be non-NULL, but maybe it
3529  * got reset to NULL without the state being changed appropriately?
3530  */
3531  GNUNET_break(0);
3532  return GNUNET_OK;
3533  }
3534 
3535  /* Reset backoff for primary address */
3538  return GNUNET_OK;
3539 }
3540 
3541 
3548 int
3550 {
3551  return test_connected(lookup_neighbour(target));
3552 }
3553 
3554 
3560 static void
3562 {
3563  struct NeighbourMapEntry *n = cls;
3564 
3565  n->delayed_disconnect_task = NULL;
3567  "Disconnecting by request from peer %s\n",
3568  GNUNET_i2s(&n->id));
3569  free_neighbour(n);
3570 }
3571 
3572 
3580 void
3582  const struct GNUNET_MessageHeader *msg)
3583 {
3584  struct NeighbourMapEntry *n;
3585  const struct GNUNET_ATS_SessionQuotaMessage *sqm;
3586  struct GNUNET_BANDWIDTH_Value32NBO last;
3587 
3589  "Received QUOTA message from peer `%s'\n",
3590  GNUNET_i2s(peer));
3591  if (ntohs(msg->size) != sizeof(struct GNUNET_ATS_SessionQuotaMessage))
3592  {
3593  GNUNET_break_op(0);
3595  gettext_noop("# quota messages ignored (malformed)"),
3596  1,
3597  GNUNET_NO);
3598  return;
3599  }
3601  gettext_noop
3602  ("# QUOTA messages received"),
3603  1, GNUNET_NO);
3604  sqm = (const struct GNUNET_ATS_SessionQuotaMessage *)msg;
3605  if (NULL == (n = lookup_neighbour(peer)))
3606  {
3607  /* gone already */
3608  return;
3609  }
3611  GNUNET_BANDWIDTH_value_init(ntohl(sqm->quota)));
3612  if (last.value__ != n->neighbour_receive_quota.value__)
3613  {
3614  n->neighbour_receive_quota = last;
3616  }
3617 }
3618 
3619 
3627 void
3629  const struct GNUNET_MessageHeader *msg)
3630 {
3631  struct NeighbourMapEntry *n;
3632  const struct GNUNET_ATS_SessionDisconnectMessage *sdm;
3633 
3635  "Received DISCONNECT message from peer `%s'\n",
3636  GNUNET_i2s(peer));
3637  if (ntohs(msg->size) != sizeof(struct GNUNET_ATS_SessionDisconnectMessage))
3638  {
3639  GNUNET_break_op(0);
3641  gettext_noop
3642  ("# disconnect messages ignored (malformed)"),
3643  1,
3644  GNUNET_NO);
3645  return;
3646  }
3648  gettext_noop
3649  ("# DISCONNECT messages received"),
3650  1, GNUNET_NO);
3651  sdm = (const struct GNUNET_ATS_SessionDisconnectMessage *)msg;
3652  if (NULL == (n = lookup_neighbour(peer)))
3653  {
3654  /* gone already */
3655  return;
3656  }
3658  {
3660  gettext_noop("# disconnect messages ignored (timestamp)"),
3661  1,
3662  GNUNET_NO);
3663  return;
3664  }
3665  if (0 != memcmp(peer,
3666  &sdm->public_key,
3667  sizeof(struct GNUNET_PeerIdentity)))
3668  {
3669  GNUNET_break_op(0);
3670  return;
3671  }
3672  if (ntohl(sdm->purpose.size) !=
3673  sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) +
3674  sizeof(struct GNUNET_CRYPTO_EddsaPublicKey) +
3675  sizeof(struct GNUNET_TIME_AbsoluteNBO))
3676  {
3678  "DISCONNECT message from peer `%s' has invalid size\n",
3679  GNUNET_i2s(peer));
3680  GNUNET_break_op(0);
3681  return;
3682  }
3683  if (GNUNET_OK !=
3685  &sdm->purpose,
3686  &sdm->signature,
3687  &sdm->public_key))
3688  {
3690  "DISCONNECT message from peer `%s' cannot be verified \n",
3691  GNUNET_i2s(peer));
3692  GNUNET_break_op(0);
3693  return;
3694  }
3695  if (NULL == n->delayed_disconnect_task)
3696  {
3698  n);
3699  }
3700 }
3701 
3702 
3711 
3715  void *cb_cls;
3716 };
3717 
3718 
3727 static int
3729  const struct GNUNET_PeerIdentity *key,
3730  void *value)
3731 {
3732  struct IteratorContext *ic = cls;
3733  struct NeighbourMapEntry *n = value;
3734  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
3735  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
3736 
3737  (void)key;
3738  if (NULL != n->primary_address.address)
3739  {
3740  bandwidth_in = n->primary_address.bandwidth_in;
3741  bandwidth_out = n->primary_address.bandwidth_out;
3742  }
3743  else
3744  {
3745  bandwidth_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
3746  bandwidth_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
3747  }
3748  ic->cb(ic->cb_cls,
3749  &n->id,
3751  n->state,
3752  n->timeout,
3753  bandwidth_in, bandwidth_out);
3754  return GNUNET_OK;
3755 }
3756 
3757 
3764 void
3766  void *cb_cls)
3767 {
3768  struct IteratorContext ic;
3769 
3770  if (NULL == neighbours)
3771  return; /* can happen during shutdown */
3772  ic.cb = cb;
3773  ic.cb_cls = cb_cls;
3776  &ic);
3777 }
3778 
3779 
3785 void
3787 {
3788  struct NeighbourMapEntry *n;
3789 
3790  if (NULL == (n = lookup_neighbour(target)))
3791  return; /* not active */
3792  if (GNUNET_YES == test_connected(n))
3794  gettext_noop("# disconnected from peer upon explicit request"),
3795  1,
3796  GNUNET_NO);
3798  "Forced disconnect from peer %s\n",
3799  GNUNET_i2s(target));
3801 }
3802 
3803 
3810 const struct GNUNET_HELLO_Address *
3812 {
3813  struct NeighbourMapEntry *n;
3814 
3815  n = lookup_neighbour(peer);
3816  if (NULL == n)
3817  return NULL;
3818  return n->primary_address.address;
3819 }
3820 
3821 
3827 void
3828 GST_neighbours_start(unsigned int max_fds)
3829 {
3830  (void)max_fds;
3832  GNUNET_NO);
3835  NULL);
3836 }
3837 
3838 
3847 static int
3849  const struct GNUNET_PeerIdentity *key,
3850  void *value)
3851 {
3852  struct NeighbourMapEntry *n = value;
3853 
3854  (void)cls;
3855  (void)key;
3857  "Disconnecting peer `%4s' during shutdown\n",
3858  GNUNET_i2s(&n->id));
3859  free_neighbour(n);
3860  return GNUNET_OK;
3861 }
3862 
3863 
3867 void
3869 {
3870  if (NULL == neighbours)
3871  return;
3872  if (NULL != util_transmission_tk)
3873  {
3874  GNUNET_SCHEDULER_cancel(util_transmission_tk);
3875  util_transmission_tk = NULL;
3876  }
3879  NULL);
3881  neighbours = NULL;
3882 }
3883 
3884 
3885 /* 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:139
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:671
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:120
struct GST_BlacklistCheck * blc
Handle to the blacklist check we are performing.
int GST_neighbours_test_connected(const struct GNUNET_PeerIdentity *target)
Test if we&#39;re connected to the given peer.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
struct GNUNET_TIME_Absolute timeout
Time where we should cut the connection (timeout) if we don&#39;t make progress in the state machine (or ...
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA
Message exchanged between transport services to indicate that the sender should limit its transmissio...
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_BANDWIDTH_Value32NBO quota_out
Current outbound quota for this peer.
Definition: transport.h:133
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.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
Struct to track available bandwidth.
void GST_clients_broadcast_peer_notification(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout)
Broadcast the new active address to all clients monitoring the peer.
Message a peer sends to another when connected to indicate that the other peer should limit transmiss...
#define GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT
Bandwidth (in/out) to assume initially (before either peer has communicated any particular preference...
interfacing between transport and ATS service
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_NO
Definition: gnunet_common.h:78
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint32_t quota
Quota to use (for sending), in bytes per second.
void GNUNET_ATS_connectivity_suggest_cancel(struct GNUNET_ATS_ConnectivitySuggestHandle *sh)
We no longer care about being connected to a peer.
void GST_neighbours_keepalive(const struct GNUNET_PeerIdentity *neighbour, const struct GNUNET_MessageHeader *m)
Keep the connection to the given neighbour alive longer, we received a KEEPALIVE (or equivalent); sen...
Received a SYN, asking ATS about address suggestions.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
Entry in a DLL we use to keep track of pending blacklist checks.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
static char * print_ack_state(enum GST_ACK_State s)
Convert the given ACK state to a string.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
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:176
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE
Response to a GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE message to measure latency in a regular...
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT
Message from TRANSPORT notifying about a client that connected to us.
int GNUNET_TRANSPORT_is_connected(enum GNUNET_TRANSPORT_PeerState state)
Check if a state is defined as connected.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
uint32_t value__
The actual value (bytes per second).
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_ATS_ConnectivitySuggestHandle * GNUNET_ATS_connectivity_suggest(struct GNUNET_ATS_ConnectivityHandle *ch, const struct GNUNET_PeerIdentity *peer, uint32_t strength)
We would like to receive address suggestions for a peer.
static unsigned int neighbours_connected
counter for connected neighbours
int GST_neighbours_handle_session_syn_ack(const struct GNUNET_MessageHeader *message, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
We received a &#39;SESSION_SYN_ACK&#39; message from the other peer.
void GST_neighbours_start(unsigned int max_fds)
Initialize the neighbours subsystem.
struct GNUNET_TIME_Relative GST_neighbours_calculate_receive_delay(const struct GNUNET_PeerIdentity *sender, ssize_t size, int *do_forward)
We have received a message from the given sender.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
Message a peer sends to another to indicate that it intends to setup a connection/session for data ex...
static void delayed_disconnect(void *cls)
Task to asynchronously run free_neighbour().
int GNUNET_HELLO_address_check_option(const struct GNUNET_HELLO_Address *address, enum GNUNET_HELLO_AddressInfo option)
Check if an address has a local option set.
Definition: address.c:39
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c: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:186
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:1237
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.
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:1264
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:686
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:116
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:172
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out
Outbound bandwidth that was assigned to address.
int ats_active
Did we tell ATS that this is our &#39;active&#39; address?
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static struct GNUNET_SCHEDULER_Task * util_transmission_tk
Task transmitting utilization data.
static struct NeighbourMapEntry * lookup_neighbour(const struct GNUNET_PeerIdentity *pid)
Lookup a neighbour entry in the neighbours hash map.
static unsigned long long bytes_in_send_queue
Number of bytes we have currently queued for transmission.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE
Message send by a peer to notify the other to keep the session alive and measure latency in a regular...
const char * message_buf
The message(s) we want to transmit, GNUNET_MessageHeader(s) stuck together in memory.
#define MAX_BANDWIDTH_CARRY_S
Number of seconds that available bandwidth carries over (can accumulate).
struct GNUNET_TIME_Relative GNUNET_BANDWIDTH_tracker_get_delay(struct GNUNET_BANDWIDTH_Tracker *av, size_t size)
Compute how long we should wait until consuming size bytes of bandwidth in order to stay within the g...
Definition: bandwidth.c:458
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:272
#define QUOTA_VIOLATION_DROP_THRESHOLD
How often must a peer violate bandwidth quotas before we start to simply drop its messages...
const char * GNUNET_TRANSPORT_ps2s(enum GNUNET_TRANSPORT_PeerState state)
Convert a transport state to a human readable string.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
GST_NeighbourIterator cb
Function to call on each connected neighbour.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:66
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:181
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:131
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:77
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition: time.c: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:741
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:1214
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:655
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:956
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...