aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO9
-rw-r--r--src/core/core_api.c16
-rw-r--r--src/core/gnunet-service-core.c406
-rw-r--r--src/core/test_core_api.c8
-rw-r--r--src/core/test_core_api_reliability.c9
-rw-r--r--src/core/test_core_quota_compliance.c9
6 files changed, 281 insertions, 176 deletions
diff --git a/TODO b/TODO
index c3a81fe3a..ea7e612bb 100644
--- a/TODO
+++ b/TODO
@@ -1,14 +1,6 @@
10.9.0pre2: 10.9.0pre2:
2* BIG CORE REFACTORING:
3 - fix transport plugin API (ATS!) [mw]
4 - fix DV [nate]
5* Integration test: 2* Integration test:
6 - test bootstrapping via hostlist + transport/core/dht connect 3 - test bootstrapping via hostlist + transport/core/dht connect
7* CORE:
8 - Jun 27 11:51:54 core-7670 ERROR Assertion failed at gnunet-service-core.c:3616.
9 (transport notified us that we connected to ourselves!!!; can we still reproduce this?)
10 => Also, we may want to issue a 'connect to ourselves' automatically on start of
11 core_api AND allow messages to self [CG/phillip]
12 4
130.9.0pre3: 50.9.0pre3:
14* TRANSPORT: [MW] 6* TRANSPORT: [MW]
@@ -35,6 +27,7 @@
35 + insert 27 + insert
36 + download 28 + download
37 + search 29 + search
30 - implement anonymity level > 1
38* GNUNET-GTK: [CG] 31* GNUNET-GTK: [CG]
39 - figure out where in the GUI we should show active upload operations and allow aborts 32 - figure out where in the GUI we should show active upload operations and allow aborts
40 - handle events: 33 - handle events:
diff --git a/src/core/core_api.c b/src/core/core_api.c
index 21622852b..f73e1f290 100644
--- a/src/core/core_api.c
+++ b/src/core/core_api.c
@@ -881,6 +881,22 @@ main_notify_handler (void *cls,
881 "Successfully reconnected to core service.\n"); 881 "Successfully reconnected to core service.\n");
882#endif 882#endif
883 } 883 }
884 /* fake 'connect to self' */
885 pr = GNUNET_CONTAINER_multihashmap_get (h->peers,
886 &h->me.hashPubKey);
887 GNUNET_assert (pr == NULL);
888 pr = GNUNET_malloc (sizeof (struct PeerRecord));
889 pr->peer = h->me;
890 pr->ch = h;
891 GNUNET_assert (GNUNET_YES ==
892 GNUNET_CONTAINER_multihashmap_put (h->peers,
893 &h->me.hashPubKey,
894 pr,
895 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
896 if (NULL != h->connects)
897 h->connects (h->cls,
898 &h->me,
899 NULL);
884 break; 900 break;
885 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT: 901 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT:
886 if (msize < sizeof (struct ConnectNotifyMessage)) 902 if (msize < sizeof (struct ConnectNotifyMessage))
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c
index 76e26cc8f..8bac3e7e7 100644
--- a/src/core/gnunet-service-core.c
+++ b/src/core/gnunet-service-core.c
@@ -153,9 +153,25 @@
153 */ 153 */
154enum PeerStateMachine 154enum PeerStateMachine
155{ 155{
156 /**
157 * No handshake yet.
158 */
156 PEER_STATE_DOWN, 159 PEER_STATE_DOWN,
160
161 /**
162 * We've sent our session key.
163 */
157 PEER_STATE_KEY_SENT, 164 PEER_STATE_KEY_SENT,
165
166 /**
167 * We've received the other peers session key.
168 */
158 PEER_STATE_KEY_RECEIVED, 169 PEER_STATE_KEY_RECEIVED,
170
171 /**
172 * The other peer has confirmed our session key with a message
173 * encrypted with his session key (which we got). Session is now fully up.
174 */
159 PEER_STATE_KEY_CONFIRMED 175 PEER_STATE_KEY_CONFIRMED
160}; 176};
161 177
@@ -402,10 +418,6 @@ struct ClientActiveRequest;
402 */ 418 */
403struct Neighbour 419struct Neighbour
404{ 420{
405 /**
406 * We keep neighbours in a linked list (for now).
407 */
408 struct Neighbour *next;
409 421
410 /** 422 /**
411 * Unencrypted messages destined for this peer. 423 * Unencrypted messages destined for this peer.
@@ -769,9 +781,14 @@ static struct Client *clients;
769static struct GNUNET_SERVER_NotificationContext *notifier; 781static struct GNUNET_SERVER_NotificationContext *notifier;
770 782
771/** 783/**
772 * We keep neighbours in a linked list (for now). 784 * Map of peer identities to 'struct Neighbour'.
785 */
786static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
787
788/**
789 * Neighbour entry for "this" peer.
773 */ 790 */
774static struct Neighbour *neighbours; 791static struct Neighbour self;
775 792
776/** 793/**
777 * For creating statistics. 794 * For creating statistics.
@@ -784,13 +801,7 @@ static struct GNUNET_STATISTICS_Handle *stats;
784static unsigned long long preference_sum; 801static unsigned long long preference_sum;
785 802
786/** 803/**
787 * Total number of neighbours we have.
788 */
789static unsigned int neighbour_count;
790
791/**
792 * How much inbound bandwidth are we supposed to be using per second? 804 * How much inbound bandwidth are we supposed to be using per second?
793 * FIXME: this value is not used!
794 */ 805 */
795static unsigned long long bandwidth_target_in_bps; 806static unsigned long long bandwidth_target_in_bps;
796 807
@@ -885,6 +896,23 @@ get_neighbour_timeout (struct Neighbour *n)
885 896
886 897
887/** 898/**
899 * Helper function for update_preference_sum.
900 */
901static int
902update_preference (void *cls,
903 const GNUNET_HashCode *key,
904 void *value)
905{
906 unsigned long long *ps = cls;
907 struct Neighbour *n = value;
908
909 n->current_preference /= 2;
910 *ps += n->current_preference;
911 return GNUNET_OK;
912}
913
914
915/**
888 * A preference value for a neighbour was update. Update 916 * A preference value for a neighbour was update. Update
889 * the preference sum accordingly. 917 * the preference sum accordingly.
890 * 918 *
@@ -893,7 +921,6 @@ get_neighbour_timeout (struct Neighbour *n)
893static void 921static void
894update_preference_sum (unsigned long long inc) 922update_preference_sum (unsigned long long inc)
895{ 923{
896 struct Neighbour *n;
897 unsigned long long os; 924 unsigned long long os;
898 925
899 os = preference_sum; 926 os = preference_sum;
@@ -902,13 +929,9 @@ update_preference_sum (unsigned long long inc)
902 return; /* done! */ 929 return; /* done! */
903 /* overflow! compensate by cutting all values in half! */ 930 /* overflow! compensate by cutting all values in half! */
904 preference_sum = 0; 931 preference_sum = 0;
905 n = neighbours; 932 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
906 while (n != NULL) 933 &update_preference,
907 { 934 &preference_sum);
908 n->current_preference /= 2;
909 preference_sum += n->current_preference;
910 n = n->next;
911 }
912 GNUNET_STATISTICS_set (stats, gettext_noop ("# total peer preference"), preference_sum, GNUNET_NO); 935 GNUNET_STATISTICS_set (stats, gettext_noop ("# total peer preference"), preference_sum, GNUNET_NO);
913} 936}
914 937
@@ -923,14 +946,7 @@ update_preference_sum (unsigned long long inc)
923static struct Neighbour * 946static struct Neighbour *
924find_neighbour (const struct GNUNET_PeerIdentity *peer) 947find_neighbour (const struct GNUNET_PeerIdentity *peer)
925{ 948{
926 struct Neighbour *ret; 949 return GNUNET_CONTAINER_multihashmap_get (neighbours, &peer->hashPubKey);
927
928 ret = neighbours;
929 while ((ret != NULL) &&
930 (0 != memcmp (&ret->peer,
931 peer, sizeof (struct GNUNET_PeerIdentity))))
932 ret = ret->next;
933 return ret;
934} 950}
935 951
936 952
@@ -1068,33 +1084,42 @@ schedule_peer_messages (struct Neighbour *n)
1068 unsigned int queue_size; 1084 unsigned int queue_size;
1069 1085
1070 /* check if neighbour queue is empty enough! */ 1086 /* check if neighbour queue is empty enough! */
1071 queue_size = 0; 1087 if (n != &self)
1072 mqe = n->messages;
1073 while (mqe != NULL)
1074 {
1075 queue_size++;
1076 mqe = mqe->next;
1077 }
1078 if (queue_size >= MAX_PEER_QUEUE_SIZE)
1079 { 1088 {
1089 queue_size = 0;
1090 mqe = n->messages;
1091 while (mqe != NULL)
1092 {
1093 queue_size++;
1094 mqe = mqe->next;
1095 }
1096 if (queue_size >= MAX_PEER_QUEUE_SIZE)
1097 {
1080#if DEBUG_CORE_CLIENT 1098#if DEBUG_CORE_CLIENT
1081 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1099 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1082 "Not considering client transmission requests: queue full\n"); 1100 "Not considering client transmission requests: queue full\n");
1083#endif 1101#endif
1084 return; /* queue still full */ 1102 return; /* queue still full */
1103 }
1104 /* find highest priority request */
1105 pos = n->active_client_request_head;
1106 car = NULL;
1107 while (pos != NULL)
1108 {
1109 if ( (car == NULL) ||
1110 (pos->priority > car->priority) )
1111 car = pos;
1112 pos = pos->next;
1113 }
1114 if (car == NULL)
1115 return; /* no pending requests */
1085 } 1116 }
1086 /* find highest priority request */ 1117 else
1087 pos = n->active_client_request_head;
1088 car = NULL;
1089 while (pos != NULL)
1090 { 1118 {
1091 if ( (car == NULL) || 1119 car = n->active_client_request_head;
1092 (pos->priority > car->priority) ) 1120 if (car == NULL)
1093 car = pos; 1121 return;
1094 pos = pos->next;
1095 } 1122 }
1096 if (car == NULL)
1097 return; /* no pending requests */
1098#if DEBUG_CORE_CLIENT 1123#if DEBUG_CORE_CLIENT
1099 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1124 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1100 "Permitting client transmission request to `%s'\n", 1125 "Permitting client transmission request to `%s'\n",
@@ -1131,7 +1156,12 @@ handle_client_send_request (void *cls,
1131 struct ClientActiveRequest *car; 1156 struct ClientActiveRequest *car;
1132 1157
1133 req = (const struct SendMessageRequest*) message; 1158 req = (const struct SendMessageRequest*) message;
1134 n = find_neighbour (&req->peer); 1159 if (0 == memcmp (&req->peer,
1160 &my_identity,
1161 sizeof (struct GNUNET_PeerIdentity)))
1162 n = &self;
1163 else
1164 n = find_neighbour (&req->peer);
1135 if ( (n == NULL) || 1165 if ( (n == NULL) ||
1136 (GNUNET_YES != n->is_connected) || 1166 (GNUNET_YES != n->is_connected) ||
1137 (n->status != PEER_STATE_KEY_CONFIRMED) ) 1167 (n->status != PEER_STATE_KEY_CONFIRMED) )
@@ -1194,6 +1224,57 @@ handle_client_send_request (void *cls,
1194 1224
1195 1225
1196/** 1226/**
1227 * Notify client about an existing connection to one of our neighbours.
1228 */
1229static int
1230notify_client_about_neighbour (void *cls,
1231 const GNUNET_HashCode *key,
1232 void *value)
1233{
1234 struct Client *c = cls;
1235 struct Neighbour *n = value;
1236 size_t size;
1237 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
1238 struct GNUNET_TRANSPORT_ATS_Information *ats;
1239 struct ConnectNotifyMessage *cnm;
1240
1241 size = sizeof (struct ConnectNotifyMessage) +
1242 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1243 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1244 {
1245 GNUNET_break (0);
1246 /* recovery strategy: throw away performance data */
1247 GNUNET_array_grow (n->ats,
1248 n->ats_count,
1249 0);
1250 size = sizeof (struct ConnectNotifyMessage) +
1251 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1252 }
1253 cnm = (struct ConnectNotifyMessage*) buf;
1254 cnm->header.size = htons (size);
1255 cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1256 cnm->ats_count = htonl (n->ats_count);
1257 ats = &cnm->ats;
1258 memcpy (ats,
1259 n->ats,
1260 sizeof (struct GNUNET_TRANSPORT_ATS_Information) * n->ats_count);
1261 ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1262 ats[n->ats_count].value = htonl (0);
1263 if (n->status == PEER_STATE_KEY_CONFIRMED)
1264 {
1265#if DEBUG_CORE_CLIENT
1266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1267 "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
1268#endif
1269 cnm->peer = n->peer;
1270 send_to_client (c, &cnm->header, GNUNET_NO);
1271 }
1272 return GNUNET_OK;
1273}
1274
1275
1276
1277/**
1197 * Handle CORE_INIT request. 1278 * Handle CORE_INIT request.
1198 */ 1279 */
1199static void 1280static void
@@ -1207,11 +1288,6 @@ handle_client_init (void *cls,
1207 uint16_t msize; 1288 uint16_t msize;
1208 const uint16_t *types; 1289 const uint16_t *types;
1209 uint16_t *wtypes; 1290 uint16_t *wtypes;
1210 struct Neighbour *n;
1211 struct ConnectNotifyMessage *cnm;
1212 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
1213 struct GNUNET_TRANSPORT_ATS_Information *ats;
1214 size_t size;
1215 unsigned int i; 1291 unsigned int i;
1216 1292
1217#if DEBUG_CORE_CLIENT 1293#if DEBUG_CORE_CLIENT
@@ -1273,42 +1349,9 @@ handle_client_init (void *cls,
1273 if (0 != (c->options & GNUNET_CORE_OPTION_SEND_CONNECT)) 1349 if (0 != (c->options & GNUNET_CORE_OPTION_SEND_CONNECT))
1274 { 1350 {
1275 /* notify new client about existing neighbours */ 1351 /* notify new client about existing neighbours */
1276 n = neighbours; 1352 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
1277 while (n != NULL) 1353 &notify_client_about_neighbour,
1278 { 1354 c);
1279 size = sizeof (struct ConnectNotifyMessage) +
1280 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1281 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1282 {
1283 GNUNET_break (0);
1284 /* recovery strategy: throw away performance data */
1285 GNUNET_array_grow (n->ats,
1286 n->ats_count,
1287 0);
1288 size = sizeof (struct ConnectNotifyMessage) +
1289 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1290 }
1291 cnm = (struct ConnectNotifyMessage*) buf;
1292 cnm->header.size = htons (size);
1293 cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1294 cnm->ats_count = htonl (n->ats_count);
1295 ats = &cnm->ats;
1296 memcpy (ats,
1297 n->ats,
1298 sizeof (struct GNUNET_TRANSPORT_ATS_Information) * n->ats_count);
1299 ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1300 ats[n->ats_count].value = htonl (0);
1301 if (n->status == PEER_STATE_KEY_CONFIRMED)
1302 {
1303#if DEBUG_CORE_CLIENT
1304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1305 "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
1306#endif
1307 cnm->peer = n->peer;
1308 send_to_client (c, &cnm->header, GNUNET_NO);
1309 }
1310 n = n->next;
1311 }
1312 } 1355 }
1313 GNUNET_SERVER_receive_done (client, GNUNET_OK); 1356 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1314} 1357}
@@ -1390,6 +1433,58 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1390 1433
1391 1434
1392/** 1435/**
1436 * Helper function for handle_client_iterate_peers.
1437 */
1438static int
1439queue_connect_message (void *cls,
1440 const GNUNET_HashCode *key,
1441 void *value)
1442{
1443 struct GNUNET_SERVER_TransmitContext *tc = cls;
1444 struct Neighbour *n = value;
1445 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
1446 struct GNUNET_TRANSPORT_ATS_Information *ats;
1447 size_t size;
1448 struct ConnectNotifyMessage *cnm;
1449
1450 cnm = (struct ConnectNotifyMessage*) buf;
1451 if (n->status != PEER_STATE_KEY_CONFIRMED)
1452 return GNUNET_OK;
1453 size = sizeof (struct ConnectNotifyMessage) +
1454 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1455 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1456 {
1457 GNUNET_break (0);
1458 /* recovery strategy: throw away performance data */
1459 GNUNET_array_grow (n->ats,
1460 n->ats_count,
1461 0);
1462 size = sizeof (struct PeerStatusNotifyMessage) +
1463 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1464 }
1465 cnm = (struct ConnectNotifyMessage*) buf;
1466 cnm->header.size = htons (size);
1467 cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1468 cnm->ats_count = htonl (n->ats_count);
1469 ats = &cnm->ats;
1470 memcpy (ats,
1471 n->ats,
1472 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
1473 ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1474 ats[n->ats_count].value = htonl (0);
1475#if DEBUG_CORE_CLIENT
1476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1477 "Sending `%s' message to client.\n",
1478 "NOTIFY_CONNECT");
1479#endif
1480 cnm->peer = n->peer;
1481 GNUNET_SERVER_transmit_context_append_message (tc,
1482 &cnm->header);
1483 return GNUNET_OK;
1484}
1485
1486
1487/**
1393 * Handle CORE_ITERATE_PEERS request. 1488 * Handle CORE_ITERATE_PEERS request.
1394 * 1489 *
1395 * @param cls unused 1490 * @param cls unused
@@ -1402,55 +1497,12 @@ handle_client_iterate_peers (void *cls,
1402 const struct GNUNET_MessageHeader *message) 1497 const struct GNUNET_MessageHeader *message)
1403 1498
1404{ 1499{
1405 struct Neighbour *n;
1406 struct ConnectNotifyMessage *cnm;
1407 struct GNUNET_MessageHeader done_msg; 1500 struct GNUNET_MessageHeader done_msg;
1408 struct GNUNET_SERVER_TransmitContext *tc; 1501 struct GNUNET_SERVER_TransmitContext *tc;
1409 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
1410 struct GNUNET_TRANSPORT_ATS_Information *ats;
1411 size_t size;
1412 1502
1413 /* notify new client about existing neighbours */ 1503 /* notify new client about existing neighbours */
1414 tc = GNUNET_SERVER_transmit_context_create (client); 1504 tc = GNUNET_SERVER_transmit_context_create (client);
1415 cnm = (struct ConnectNotifyMessage*) buf; 1505 GNUNET_CONTAINER_multihashmap_iterate (neighbours, &queue_connect_message, tc);
1416 n = neighbours;
1417 while (n != NULL)
1418 {
1419 if (n->status == PEER_STATE_KEY_CONFIRMED)
1420 {
1421 size = sizeof (struct ConnectNotifyMessage) +
1422 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1423 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1424 {
1425 GNUNET_break (0);
1426 /* recovery strategy: throw away performance data */
1427 GNUNET_array_grow (n->ats,
1428 n->ats_count,
1429 0);
1430 size = sizeof (struct PeerStatusNotifyMessage) +
1431 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1432 }
1433 cnm = (struct ConnectNotifyMessage*) buf;
1434 cnm->header.size = htons (size);
1435 cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1436 cnm->ats_count = htonl (n->ats_count);
1437 ats = &cnm->ats;
1438 memcpy (ats,
1439 n->ats,
1440 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
1441 ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1442 ats[n->ats_count].value = htonl (0);
1443#if DEBUG_CORE_CLIENT
1444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1445 "Sending `%s' message to client.\n",
1446 "NOTIFY_CONNECT");
1447#endif
1448 cnm->peer = n->peer;
1449 GNUNET_SERVER_transmit_context_append_message (tc,
1450 &cnm->header);
1451 }
1452 n = n->next;
1453 }
1454 done_msg.size = htons (sizeof (struct GNUNET_MessageHeader)); 1506 done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
1455 done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END); 1507 done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
1456 GNUNET_SERVER_transmit_context_append_message (tc, &done_msg); 1508 GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
@@ -1792,8 +1844,6 @@ consider_free_task (void *cls,
1792static void 1844static void
1793consider_free_neighbour (struct Neighbour *n) 1845consider_free_neighbour (struct Neighbour *n)
1794{ 1846{
1795 struct Neighbour *pos;
1796 struct Neighbour *prev;
1797 struct GNUNET_TIME_Relative left; 1847 struct GNUNET_TIME_Relative left;
1798 1848
1799 if ( (n->th != NULL) || 1849 if ( (n->th != NULL) ||
@@ -1812,22 +1862,13 @@ consider_free_neighbour (struct Neighbour *n)
1812 return; 1862 return;
1813 } 1863 }
1814 /* actually free the neighbour... */ 1864 /* actually free the neighbour... */
1815 prev = NULL; 1865 GNUNET_assert (GNUNET_OK ==
1816 pos = neighbours; 1866 GNUNET_CONTAINER_multihashmap_remove (neighbours,
1817 while (pos != n) 1867 &n->peer.hashPubKey,
1818 { 1868 n));
1819 prev = pos;
1820 pos = pos->next;
1821 }
1822 if (prev == NULL)
1823 neighbours = n->next;
1824 else
1825 prev->next = n->next;
1826 GNUNET_assert (neighbour_count > 0);
1827 neighbour_count--;
1828 GNUNET_STATISTICS_set (stats, 1869 GNUNET_STATISTICS_set (stats,
1829 gettext_noop ("# neighbour entries allocated"), 1870 gettext_noop ("# neighbour entries allocated"),
1830 neighbour_count, 1871 GNUNET_CONTAINER_multihashmap_size (neighbours),
1831 GNUNET_NO); 1872 GNUNET_NO);
1832 free_neighbour (n); 1873 free_neighbour (n);
1833} 1874}
@@ -2643,10 +2684,6 @@ create_neighbour (const struct GNUNET_PeerIdentity *pid)
2643 GNUNET_i2s (pid)); 2684 GNUNET_i2s (pid));
2644#endif 2685#endif
2645 n = GNUNET_malloc (sizeof (struct Neighbour)); 2686 n = GNUNET_malloc (sizeof (struct Neighbour));
2646 n->next = neighbours;
2647 neighbours = n;
2648 neighbour_count++;
2649 GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), neighbour_count, GNUNET_NO);
2650 n->peer = *pid; 2687 n->peer = *pid;
2651 GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key); 2688 GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key);
2652 now = GNUNET_TIME_absolute_get (); 2689 now = GNUNET_TIME_absolute_get ();
@@ -2659,6 +2696,13 @@ create_neighbour (const struct GNUNET_PeerIdentity *pid)
2659 n->bw_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT; 2696 n->bw_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2660 n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 2697 n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
2661 UINT32_MAX); 2698 UINT32_MAX);
2699 GNUNET_assert (GNUNET_OK ==
2700 GNUNET_CONTAINER_multihashmap_put (neighbours,
2701 &n->peer.hashPubKey,
2702 n,
2703 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2704 GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"),
2705 GNUNET_CONTAINER_multihashmap_size (neighbours), GNUNET_NO);
2662 neighbour_quota_update (n, NULL); 2706 neighbour_quota_update (n, NULL);
2663 consider_free_neighbour (n); 2707 consider_free_neighbour (n);
2664 return n; 2708 return n;
@@ -2702,10 +2746,15 @@ handle_client_send (void *cls,
2702 msize -= sizeof (struct SendMessage); 2746 msize -= sizeof (struct SendMessage);
2703 if (0 == memcmp (&sm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity))) 2747 if (0 == memcmp (&sm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
2704 { 2748 {
2705 /* FIXME: should we not allow loopback-injection here? */ 2749 /* loopback */
2706 GNUNET_break (0); 2750 GNUNET_SERVER_mst_receive (mst,
2751 &self,
2752 (const char*) &sm[1],
2753 msize,
2754 GNUNET_YES,
2755 GNUNET_NO);
2707 if (client != NULL) 2756 if (client != NULL)
2708 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 2757 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2709 return; 2758 return;
2710 } 2759 }
2711 n = find_neighbour (&sm->peer); 2760 n = find_neighbour (&sm->peer);
@@ -4225,6 +4274,7 @@ neighbour_quota_update (void *cls,
4225 unsigned long long distributable; 4274 unsigned long long distributable;
4226 uint64_t need_per_peer; 4275 uint64_t need_per_peer;
4227 uint64_t need_per_second; 4276 uint64_t need_per_second;
4277 unsigned int neighbour_count;
4228 4278
4229#if DEBUG_CORE 4279#if DEBUG_CORE
4230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 4280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -4236,6 +4286,9 @@ neighbour_quota_update (void *cls,
4236 divides by a bit more to avoid division by zero AND to 4286 divides by a bit more to avoid division by zero AND to
4237 account for possibility of new neighbours joining any time 4287 account for possibility of new neighbours joining any time
4238 AND to convert to double... */ 4288 AND to convert to double... */
4289 neighbour_count = GNUNET_CONTAINER_multihashmap_size (neighbours);
4290 if (neighbour_count == 0)
4291 return;
4239 if (preference_sum == 0) 4292 if (preference_sum == 0)
4240 { 4293 {
4241 pref_rel = 1.0 / (double) neighbour_count; 4294 pref_rel = 1.0 / (double) neighbour_count;
@@ -4448,30 +4501,42 @@ handle_transport_notify_disconnect (void *cls,
4448 4501
4449 4502
4450/** 4503/**
4504 * Wrapper around 'free_neighbour'; helper for 'cleaning_task'.
4505 */
4506static int
4507free_neighbour_helper (void *cls,
4508 const GNUNET_HashCode *key,
4509 void *value)
4510{
4511 struct Neighbour *n = value;
4512
4513 free_neighbour (n);
4514 return GNUNET_OK;
4515}
4516
4517
4518/**
4451 * Last task run during shutdown. Disconnects us from 4519 * Last task run during shutdown. Disconnects us from
4452 * the transport. 4520 * the transport.
4453 */ 4521 */
4454static void 4522static void
4455cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 4523cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4456{ 4524{
4457 struct Neighbour *n;
4458 struct Client *c; 4525 struct Client *c;
4459 4526
4460#if DEBUG_CORE 4527#if DEBUG_CORE
4461 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 4528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4462 "Core service shutting down.\n"); 4529 "Core service shutting down.\n");
4463#endif 4530#endif
4464 while (NULL != (n = neighbours)) 4531 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
4465 { 4532 &free_neighbour_helper,
4466 neighbours = n->next; 4533 NULL);
4467 GNUNET_assert (neighbour_count > 0); 4534 GNUNET_CONTAINER_multihashmap_destroy (neighbours);
4468 neighbour_count--; 4535 neighbours = NULL;
4469 free_neighbour (n); 4536 GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), 0, GNUNET_NO);
4470 }
4471 GNUNET_assert (transport != NULL); 4537 GNUNET_assert (transport != NULL);
4472 GNUNET_TRANSPORT_disconnect (transport); 4538 GNUNET_TRANSPORT_disconnect (transport);
4473 transport = NULL; 4539 transport = NULL;
4474 GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), neighbour_count, GNUNET_NO);
4475 GNUNET_SERVER_notification_context_destroy (notifier); 4540 GNUNET_SERVER_notification_context_destroy (notifier);
4476 notifier = NULL; 4541 notifier = NULL;
4477 while (NULL != (c = clients)) 4542 while (NULL != (c = clients))
@@ -4520,7 +4585,7 @@ run (void *cls,
4520 }; 4585 };
4521 char *keyfile; 4586 char *keyfile;
4522 4587
4523 cfg = c; 4588 cfg = c;
4524 /* parse configuration */ 4589 /* parse configuration */
4525 if ( 4590 if (
4526 (GNUNET_OK != 4591 (GNUNET_OK !=
@@ -4563,9 +4628,14 @@ run (void *cls,
4563 GNUNET_SCHEDULER_shutdown (); 4628 GNUNET_SCHEDULER_shutdown ();
4564 return; 4629 return;
4565 } 4630 }
4631 neighbours = GNUNET_CONTAINER_multihashmap_create (128);
4566 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); 4632 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
4567 GNUNET_CRYPTO_hash (&my_public_key, 4633 GNUNET_CRYPTO_hash (&my_public_key,
4568 sizeof (my_public_key), &my_identity.hashPubKey); 4634 sizeof (my_public_key), &my_identity.hashPubKey);
4635 self.public_key = &my_public_key;
4636 self.last_activity = GNUNET_TIME_UNIT_FOREVER_ABS;
4637 self.status = PEER_STATE_KEY_CONFIRMED;
4638 self.is_connected = GNUNET_YES;
4569 /* setup notification */ 4639 /* setup notification */
4570 notifier = GNUNET_SERVER_notification_context_create (server, 4640 notifier = GNUNET_SERVER_notification_context_create (server,
4571 MAX_NOTIFY_QUEUE); 4641 MAX_NOTIFY_QUEUE);
diff --git a/src/core/test_core_api.c b/src/core/test_core_api.c
index 814ebe889..cec66f020 100644
--- a/src/core/test_core_api.c
+++ b/src/core/test_core_api.c
@@ -123,6 +123,10 @@ connect_notify (void *cls,
123{ 123{
124 struct PeerContext *pc = cls; 124 struct PeerContext *pc = cls;
125 125
126 if (0 == memcmp (&pc->id,
127 peer,
128 sizeof (struct GNUNET_PeerIdentity)))
129 return;
126 GNUNET_assert (pc->connect_status == 0); 130 GNUNET_assert (pc->connect_status == 0);
127 pc->connect_status = 1; 131 pc->connect_status = 1;
128 if (pc == &p1) 132 if (pc == &p1)
@@ -154,6 +158,10 @@ disconnect_notify (void *cls,
154{ 158{
155 struct PeerContext *pc = cls; 159 struct PeerContext *pc = cls;
156 160
161 if (0 == memcmp (&pc->id,
162 peer,
163 sizeof (struct GNUNET_PeerIdentity)))
164 return;
157 pc->connect_status = 0; 165 pc->connect_status = 0;
158 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 166 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
159 "Encrypted connection to `%4s' cut\n", GNUNET_i2s (peer)); 167 "Encrypted connection to `%4s' cut\n", GNUNET_i2s (peer));
diff --git a/src/core/test_core_api_reliability.c b/src/core/test_core_api_reliability.c
index 9192c9592..7eab92b12 100644
--- a/src/core/test_core_api_reliability.c
+++ b/src/core/test_core_api_reliability.c
@@ -221,6 +221,10 @@ connect_notify (void *cls,
221{ 221{
222 struct PeerContext *pc = cls; 222 struct PeerContext *pc = cls;
223 223
224 if (0 == memcmp (&pc->id,
225 peer,
226 sizeof (struct GNUNET_PeerIdentity)))
227 return;
224 GNUNET_assert (pc->connect_status == 0); 228 GNUNET_assert (pc->connect_status == 0);
225 pc->connect_status = 1; 229 pc->connect_status = 1;
226 if (pc == &p1) 230 if (pc == &p1)
@@ -252,6 +256,11 @@ disconnect_notify (void *cls,
252 const struct GNUNET_PeerIdentity *peer) 256 const struct GNUNET_PeerIdentity *peer)
253{ 257{
254 struct PeerContext *pc = cls; 258 struct PeerContext *pc = cls;
259
260 if (0 == memcmp (&pc->id,
261 peer,
262 sizeof (struct GNUNET_PeerIdentity)))
263 return;
255 pc->connect_status = 0; 264 pc->connect_status = 0;
256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
257 "Encrypted connection to `%4s' cut\n", GNUNET_i2s (peer)); 266 "Encrypted connection to `%4s' cut\n", GNUNET_i2s (peer));
diff --git a/src/core/test_core_quota_compliance.c b/src/core/test_core_quota_compliance.c
index 7181564d8..d951113fc 100644
--- a/src/core/test_core_quota_compliance.c
+++ b/src/core/test_core_quota_compliance.c
@@ -370,6 +370,10 @@ connect_notify (void *cls,
370{ 370{
371 struct PeerContext *pc = cls; 371 struct PeerContext *pc = cls;
372 372
373 if (0 == memcmp (&pc->id,
374 peer,
375 sizeof (struct GNUNET_PeerIdentity)))
376 return;
373 GNUNET_assert (pc->connect_status == 0); 377 GNUNET_assert (pc->connect_status == 0);
374 pc->connect_status = 1; 378 pc->connect_status = 1;
375 if (pc == &p1) 379 if (pc == &p1)
@@ -405,6 +409,11 @@ disconnect_notify (void *cls,
405 const struct GNUNET_PeerIdentity *peer) 409 const struct GNUNET_PeerIdentity *peer)
406{ 410{
407 struct PeerContext *pc = cls; 411 struct PeerContext *pc = cls;
412
413 if (0 == memcmp (&pc->id,
414 peer,
415 sizeof (struct GNUNET_PeerIdentity)))
416 return;
408 pc->connect_status = 0; 417 pc->connect_status = 0;
409#if DEBUG_TRANSMISSION 418#if DEBUG_TRANSMISSION
410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 419 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,