aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-transport_neighbours.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/gnunet-service-transport_neighbours.c')
-rw-r--r--src/transport/gnunet-service-transport_neighbours.c124
1 files changed, 111 insertions, 13 deletions
diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c
index c4d4677b1..e5bc5161c 100644
--- a/src/transport/gnunet-service-transport_neighbours.c
+++ b/src/transport/gnunet-service-transport_neighbours.c
@@ -117,6 +117,28 @@ struct SessionConnectMessage
117 117
118 118
119/** 119/**
120 * Message a peer sends to another when connected to indicate that a
121 * session is in use and the peer is still alive or to respond to a keep alive.
122 * A peer sends a message with type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE
123 * to request a message with #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE.
124 * When the keep alive response with type is received, transport service
125 * will call the respective plugin to update the session timeout
126 */
127struct SessionKeepAliveMessage
128{
129 /**
130 * Header of type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE or
131 * #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE.
132 */
133 struct GNUNET_MessageHeader header;
134
135 /**
136 * A nonce to identify the session the keep alive is used for
137 */
138 uint32_t nonce GNUNET_PACKED;
139};
140
141/**
120 * Message we send to the other peer to notify him that we intentionally 142 * Message we send to the other peer to notify him that we intentionally
121 * are disconnecting (to reduce timeouts). This is just a friendly 143 * are disconnecting (to reduce timeouts). This is just a friendly
122 * notification, peers must not rely on always receiving disconnect 144 * notification, peers must not rely on always receiving disconnect
@@ -410,6 +432,10 @@ struct NeighbourAddress
410 */ 432 */
411 int ats_active; 433 int ats_active;
412 434
435 /**
436 * The current nonce sent in the last keep alive messages
437 */
438 uint32_t keep_alive_nonce;
413}; 439};
414 440
415 441
@@ -775,6 +801,7 @@ free_address (struct NeighbourAddress *na)
775 } 801 }
776 802
777 na->ats_active = GNUNET_NO; 803 na->ats_active = GNUNET_NO;
804 na->keep_alive_nonce = 0;
778 if (NULL != na->address) 805 if (NULL != na->address)
779 { 806 {
780 GNUNET_HELLO_address_free (na->address); 807 GNUNET_HELLO_address_free (na->address);
@@ -847,6 +874,7 @@ set_address (struct NeighbourAddress *na,
847 na->bandwidth_out = bandwidth_out; 874 na->bandwidth_out = bandwidth_out;
848 na->session = session; 875 na->session = session;
849 na->ats_active = is_active; 876 na->ats_active = is_active;
877 na->keep_alive_nonce = 0;
850 if (GNUNET_YES == is_active) 878 if (GNUNET_YES == is_active)
851 { 879 {
852 /* Telling ATS about new session */ 880 /* Telling ATS about new session */
@@ -1296,16 +1324,28 @@ try_transmission_to_peer (struct NeighbourMapEntry *n)
1296static void 1324static void
1297send_keepalive (struct NeighbourMapEntry *n) 1325send_keepalive (struct NeighbourMapEntry *n)
1298{ 1326{
1299 struct GNUNET_MessageHeader m; 1327 struct SessionKeepAliveMessage m;
1300 struct GNUNET_TIME_Relative timeout; 1328 struct GNUNET_TIME_Relative timeout;
1329 uint32_t nonce;
1301 1330
1302 GNUNET_assert ((S_CONNECTED == n->state) || 1331 GNUNET_assert ((S_CONNECTED == n->state) ||
1303 (S_CONNECTED_SWITCHING_BLACKLIST == n->state) || 1332 (S_CONNECTED_SWITCHING_BLACKLIST == n->state) ||
1304 (S_CONNECTED_SWITCHING_CONNECT_SENT)); 1333 (S_CONNECTED_SWITCHING_CONNECT_SENT));
1305 if (GNUNET_TIME_absolute_get_remaining (n->keep_alive_time).rel_value_us > 0) 1334 if (GNUNET_TIME_absolute_get_remaining (n->keep_alive_time).rel_value_us > 0)
1306 return; /* no keepalive needed at this time */ 1335 return; /* no keepalive needed at this time */
1307 m.size = htons (sizeof (struct GNUNET_MessageHeader)); 1336
1308 m.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE); 1337 nonce = 0; /* 0 indicates 'not set' */
1338 while (0 == nonce)
1339 nonce = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
1340
1341 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1342 "Sending keep alive response to peer `%s' with nonce %u\n",
1343 GNUNET_i2s (&n->id), nonce);
1344
1345 m.header.size = htons (sizeof (struct SessionKeepAliveMessage));
1346 m.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE);
1347 m.nonce = htonl (nonce);
1348
1309 timeout = send_with_session (n, 1349 timeout = send_with_session (n,
1310 (const void *) &m, sizeof (m), 1350 (const void *) &m, sizeof (m),
1311 UINT32_MAX /* priority */, 1351 UINT32_MAX /* priority */,
@@ -1313,9 +1353,11 @@ send_keepalive (struct NeighbourMapEntry *n)
1313 NULL, NULL); 1353 NULL, NULL);
1314 GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# keepalives sent"), 1, 1354 GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# keepalives sent"), 1,
1315 GNUNET_NO); 1355 GNUNET_NO);
1356 n->primary_address.keep_alive_nonce = nonce;
1316 n->expect_latency_response = GNUNET_YES; 1357 n->expect_latency_response = GNUNET_YES;
1317 n->last_keep_alive_time = GNUNET_TIME_absolute_get (); 1358 n->last_keep_alive_time = GNUNET_TIME_absolute_get ();
1318 n->keep_alive_time = GNUNET_TIME_relative_to_absolute (timeout); 1359 n->keep_alive_time = GNUNET_TIME_relative_to_absolute (timeout);
1360
1319} 1361}
1320 1362
1321 1363
@@ -1324,13 +1366,20 @@ send_keepalive (struct NeighbourMapEntry *n)
1324 * we received a KEEPALIVE (or equivalent); send a response. 1366 * we received a KEEPALIVE (or equivalent); send a response.
1325 * 1367 *
1326 * @param neighbour neighbour to keep alive (by sending keep alive response) 1368 * @param neighbour neighbour to keep alive (by sending keep alive response)
1369 * @param m the keep alive message containing the nonce to respond to
1327 */ 1370 */
1328void 1371void
1329GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour) 1372GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour,
1373 const struct GNUNET_MessageHeader *m)
1330{ 1374{
1331 struct NeighbourMapEntry *n; 1375 struct NeighbourMapEntry *n;
1332 struct GNUNET_MessageHeader m; 1376 const struct SessionKeepAliveMessage *msg_in;
1377 struct SessionKeepAliveMessage msg;
1333 1378
1379 if (sizeof (struct SessionKeepAliveMessage) != ntohs (m->size))
1380 return;
1381
1382 msg_in = (struct SessionKeepAliveMessage *) m;
1334 if (NULL == (n = lookup_neighbour (neighbour))) 1383 if (NULL == (n = lookup_neighbour (neighbour)))
1335 { 1384 {
1336 GNUNET_STATISTICS_update (GST_stats, 1385 GNUNET_STATISTICS_update (GST_stats,
@@ -1347,11 +1396,17 @@ GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour)
1347 1, GNUNET_NO); 1396 1, GNUNET_NO);
1348 return; 1397 return;
1349 } 1398 }
1399
1400 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1401 "Received keep alive request from peer `%s' with nonce %u\n",
1402 GNUNET_i2s (&n->id), ntohl (msg_in->nonce));
1403
1350 /* send reply to allow neighbour to measure latency */ 1404 /* send reply to allow neighbour to measure latency */
1351 m.size = htons (sizeof (struct GNUNET_MessageHeader)); 1405 msg.header.size = htons (sizeof (struct SessionKeepAliveMessage));
1352 m.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE); 1406 msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE);
1407 msg.nonce = msg_in->nonce;
1353 (void) send_with_session(n, 1408 (void) send_with_session(n,
1354 (const void *) &m, sizeof (m), 1409 (const void *) &msg, sizeof (struct SessionKeepAliveMessage),
1355 UINT32_MAX /* priority */, 1410 UINT32_MAX /* priority */,
1356 GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, 1411 GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES,
1357 NULL, NULL); 1412 NULL, NULL);
@@ -1364,14 +1419,22 @@ GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour)
1364 * plus calculated latency) to ATS. 1419 * plus calculated latency) to ATS.
1365 * 1420 *
1366 * @param neighbour neighbour to keep alive 1421 * @param neighbour neighbour to keep alive
1422 * @param m the message containing the keep alive response
1367 */ 1423 */
1368void 1424void
1369GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour) 1425GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour,
1426 const struct GNUNET_MessageHeader *m)
1370{ 1427{
1371 struct NeighbourMapEntry *n; 1428 struct NeighbourMapEntry *n;
1429 const struct SessionKeepAliveMessage *msg;
1430 struct GNUNET_TRANSPORT_PluginFunctions *papi;
1372 uint32_t latency; 1431 uint32_t latency;
1373 struct GNUNET_ATS_Information ats; 1432 struct GNUNET_ATS_Information ats;
1374 1433
1434 if (sizeof (struct SessionKeepAliveMessage) != ntohs (m->size))
1435 return;
1436
1437 msg = (const struct SessionKeepAliveMessage *) m;
1375 if (NULL == (n = lookup_neighbour (neighbour))) 1438 if (NULL == (n = lookup_neighbour (neighbour)))
1376 { 1439 {
1377 GNUNET_STATISTICS_update (GST_stats, 1440 GNUNET_STATISTICS_update (GST_stats,
@@ -1389,6 +1452,43 @@ GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour)
1389 1, GNUNET_NO); 1452 1, GNUNET_NO);
1390 return; 1453 return;
1391 } 1454 }
1455 if (NULL == n->primary_address.address)
1456 {
1457 GNUNET_STATISTICS_update (GST_stats,
1458 gettext_noop
1459 ("# KEEPALIVE_RESPONSE messages discarded (address changed)"),
1460 1, GNUNET_NO);
1461 return;
1462 }
1463 if (n->primary_address.keep_alive_nonce != ntohl (msg->nonce))
1464 {
1465 GNUNET_STATISTICS_update (GST_stats,
1466 gettext_noop
1467 ("# KEEPALIVE_RESPONSE messages discarded (wrong nonce)"),
1468 1, GNUNET_NO);
1469 return;
1470 }
1471 else
1472 {
1473 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1474 "Received keep alive response from peer `%s' for session %p\n",
1475 GNUNET_i2s (&n->id), n->primary_address.session);
1476
1477 }
1478
1479 /* Update session timeout here */
1480 if (NULL != (papi = GST_plugins_find (n->primary_address.address->transport_name)))
1481 {
1482 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1483 "Updating session for peer `%s' for session %p\n",
1484 GNUNET_i2s (&n->id), n->primary_address.session);
1485 papi->update_session_timeout (papi->cls, &n->id, n->primary_address.session);
1486 }
1487 else
1488 {
1489 GNUNET_break (0);
1490 }
1491
1392 n->expect_latency_response = GNUNET_NO; 1492 n->expect_latency_response = GNUNET_NO;
1393 n->latency = GNUNET_TIME_absolute_get_duration (n->last_keep_alive_time); 1493 n->latency = GNUNET_TIME_absolute_get_duration (n->last_keep_alive_time);
1394 n->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 1494 n->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
@@ -1404,10 +1504,8 @@ GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour)
1404 else 1504 else
1405 latency = n->latency.rel_value_us; 1505 latency = n->latency.rel_value_us;
1406 ats.value = htonl (latency); 1506 ats.value = htonl (latency);
1407 GST_ats_update_metrics (&n->id, 1507 GST_ats_update_metrics (&n->id, n->primary_address.address,
1408 n->primary_address.address, 1508 n->primary_address.session, &ats, 1);
1409 n->primary_address.session,
1410 &ats, 1);
1411} 1509}
1412 1510
1413 1511